动态规划_10(LeetCode:1049. 最后一块石头的重量 II)


一、题目

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

在这里插入图片描述

二、题解

2.0_思路

将石头分成总和相近的两堆时,碰撞后剩余的石头为最小
求得所有石头总重量

int sum=accumulate(stones.begin(),stones.end(),0)

dp数组放当前放入的最大重量
取target=sum/2(先不管sum奇偶)
问题转为背包容量为target,求能够放入的最大重量
最后返回target-dp[target]即可

2.1_动态规划

2.1.1_确认dp数组含义

先写写出二维dp数组
dp[i][v]:有i个物品,背包容量为v时,背包能够装入的最大容量
对应的一维dp数组就是将二维的中的i维度转为for循环
dp数组改为dp[v]

2.1.2_写出递推公式

要得到最大的装入量
那就应该
当前背包容量减去当前物品体积的情况若是能够装满
则当前背包就可以装满

dp[v]=max(dp[v],dp[v-stones[i] ]+stones[i] )

2.1.3_初始化

1^最后需要用到dp[target]进行运算,所以dp数组要多开一位
2^初始状态为没有物品可以选择时各个背包容量下能够放入的最大重量
所以全部初始化为0

vector<int> dp(target+1,0);

2.1.4_deBug&完整代码

deBug:
1^最开始我获取背包容量直接这样写

int target=(accumulate(stones.begin(),stones.end(),0))/2;
......
// 返回答案
return target-dp[target];

这样会导致一个问题:

当石头重量总和为奇数时,我未记录原始数据,而是直接令target对求和取半
因为target是整形变量,target后面的小数会被舍去
返回答案时我用变小的target-dp[target],答案也就少了1

应该改成:

int sum=accumulate(stones.begin(),stones.end(),0);
int target=sum/2;
......
// (sum-dp[target])表示另一堆石头的总重量
return (sum-dp[target])-dp[target];

完整代码:

#include<iostream>
#include<vector>
#include<numeric>
using namespace std;

int lastStoneWeightII(vector<int>& stones) {
	// 获取背包容量
	int sum = accumulate(stones.begin(), stones.end(), 0);
	int target = sum / 2;

	// 定义dp数组并初始化为0
	vector<int> dp(target + 1, 0);	// 要取索引为target的值进行比较,大小就要多开1
	// 由递推公式遍历dp数组
	for (int stone_i : stones)
		for (int v = target; v >= stone_i; v--)
			dp[v] = max(dp[v], dp[v - stone_i] + stone_i);
	// 返回最后的差值
	return sum - dp[target] - dp[target];
}

总结

这类题难在了如何转到背包问题上进行求解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值