leetcode 1049: 最后一块石头的重量 II

leetcode 1049: 最后一块石头的重量 II


题目描述:每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下:
如果 x == y,那么两块石头都会被完全粉碎;
如果x != y,那么重量为x的石头将会完全粉碎,而重量为 y 的石头新重量为y-x。
最后,最多只会剩下一块石头。返回此石头最小的可能重量。如果没有石头剩下,就返回 0。
输入:[2,7,4,1,8,1]
输出:1

解题步骤:该题可以转化成,将该数组分成两个集合,两个集合之差最小,集合之差最小为0.所以要找到最小差,可以转化成找到一个集合之和最接近数组总和的一半。也就是当背包容积为数组总和一半的时候bagv,此时所选择集合的最大值。
1、 状态定义:dp[i][j]表示从前i个数值中选择出的容积小于bagv的最优石头总重量,j表示剩余背包容量
2、 状态转移方程
If(j < stones[i]) dp[i][j] = dp[i-1][j]
Else dp[i][j] = max(dp[i-1][j], dp[i-1][j-stones[i]]+stones[i])
3、 初始化:初始化第1行dp数组,表示第一个数是否能够添加到容积为i的背包中
4、 输出:sum – 2*dp[nums.length][bagv]
代码

    public int lastStoneWeightII(int[] stones) {
    	int bagv = 0,sum = 0;
    	for (int i = 0; i < stones.length; i++) {
			bagv += stones[i];
		}
    	sum = bagv;
    	bagv = bagv/2;
    	int[][] dp = new int[stones.length][bagv+1];
    	dp[0][0] = 0;
    	System.out.println(bagv);
    	//初始化第1行dp数组,表示第一个数是否能够添加到容积为i的背包中
    	for(int i = 1;i<=bagv;i++) {
    		if (stones[0]<=i)
    			dp[0][i] = stones[0];
    	}
    	for (int i = 1; i < stones.length; i++) {
			for (int j = 1; j <= bagv; j++) {
				if(j < stones[i])
					dp[i][j] = dp[i-1][j];
				else
					dp[i][j] = Math.max(dp[i-1][j],Math.abs(dp[i-1][j-stones[i]]+stones[i]));
			}
		}
    	for (int i = 0; i < dp.length; i++) {
			System.out.println(Arrays.toString(dp[i]));
		}
    	return Math.abs(sum - dp[stones.length-1][bagv]*2);
    }
发布了28 篇原创文章 · 获赞 0 · 访问量 259

猜你喜欢

转载自blog.csdn.net/zy450271923/article/details/105300751