DAY36-动态规划-01背包plus

LeetCode1049. 最后一块石头的重量 II

	/**
	 * 思路:让石头分成重量相同的两堆,相撞之后剩下的石头最小
	 * @param stones
	 * @return
	 */
    public int lastStoneWeightII(int[] stones) {
    	int sum=0,n=stones.length,subsum=0;
    	for(int i=0;i<n;i++) {
    		sum+=stones[i];
    	}
    	subsum=sum;
    	sum=sum/2;
    	
    	//初始化
    	int[][] dp = new int[n+1][sum+1];
    	for(int i=1;i<=sum;i++) {
    		if(stones[0]<=i) dp[1][i]=stones[0];
    	}
    	
    	//背包
    	for(int i=1;i<=n;i++) {
    		for(int j=1;j<=sum;j++) {
    			if(stones[i-1]>j) dp[i][j]=dp[i-1][j];
    			else dp[i][j]=Math.max(dp[i-1][j], dp[i-1][j-stones[i-1]]+stones[i-1]);
    		}
    	}
    	
    	return Math.abs(subsum-dp[n][sum]-dp[n][sum]);
    }

LeetCode494. 目标和

	/**
	 * dp数组的含义:刚好能凑到总和为j的最多种方案
	 * @param nums
	 * @param target
	 * @return
	 */
    public int findTargetSumWays(int[] nums, int target) {
    	
    	int sum=0,n=nums.length,left=0;
    	for(int i=0;i<n;i++) {
    		sum+=nums[i];
    	}
    	
    	//保证target要小于sum,才能凑到
        if(sum < Math.abs(target))return 0;

    	//保证可以凑到target值,left=(sum+target)/2
    	if((sum+target)%2==1)return 0;
    	left=(sum+target)/2;
    			
    	//初始化
    	int[][] dp = new int[n+1][left+1];
    	
    	//初始化最顶列-》只有恰好等于那个数字的位置,才可以赋值
        if (nums[0] <= left) {
            dp[1][nums[0]] = 1;
        }
    	
    	//初始化最左列,这时总分数为0,如果存在0的话,便有指数(2的count0次)种方法
    	int count0=0;
    	dp[0][0]=1;
    	for(int i=1;i<=n;i++) {
    		if(nums[i-1]==0) {
    			count0++;
    		}
    		dp[i][0]=(int)Math.pow(2, count0);
    	}
    	
    	//背包
    	for(int i=1;i<=n;i++) {
    		for(int j=1;j<=left;j++) {
    			if(nums[i-1]>j) dp[i][j]=dp[i-1][j];
    			else dp[i][j]=dp[i-1][j]+dp[i-1][j-nums[i-1]];
    		}
    	}
    	return dp[n][left];
    }

LeetCode474.一和零

    public int findMaxForm(String[] strs, int m, int n) {
    	
    	int k=strs.length;
    	int [][][] dp = new int[k+1][m+1][n+1];
    	
    	for(int i=1;i<=k;i++) {
    		int[] res = find(strs[i-1]);
    		int res0=res[0];
    		int res1=res[1];
    		for(int j=0;j<=m;j++) {
    			for(int z=0;z<=n;z++) {
    				if(res0<=j&&res1<=z) dp[i][j][z]=Math.max(dp[i-1][j][z], dp[i-1][j-res0][z-res1]+1);
    				else dp[i][j][z]=dp[i-1][j][z];
    			}
    		}
    	}
    	
    	return dp[k][m][n];
    }
    
    public int[] find(String str) {
    	int [] res = new int[2];
    	for(int i=0;i<str.length();i++) {
    		res[str.charAt(i)-'0']++;
    	}
    	return res;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值