494. 目标和 - 01背包中"装满背包有几种方法"的问题
✅01背包中"装满背包有几种方法"的问题
这道题难就难在如何把题面转化为背包问题
💡由题知left + right = sum, left - right = target
,故有left = (sum + target) / 2
,则此时就转化为了装满容量为left
的背包有几种方法
当然这里要讨论一些非法情况
- 如果
sum + target < 0
,则非法 - 如果
(sum + target)
不是偶数,则非法(因为这样子凑不了left
)
dp数组的含义
dp[j]
是装满容量为j
的背包的方法数
递推公式
-
容量为
j
的背包可以怎么得来呢,可以是容量为j - nums[0]
的背包加了一个物品nums[0]
而得来,可以是容量为j - nums[1]
的背包加了一个物品nums[1]
而得来。故这里装满容量为j
的背包的方法数就是把[0, nums.size() - 1]
里面能够装下的物品(``j >= nums[i]`)的方法数都加起来 -
故由上,对于装满背包的方法数的通用公式(大概):
dp[j] += dp[j - nums[i]]
,因为是要算方法数,所以是+=
初始化
- 这里因为要递增上去,所以要得到答案,需使得
dp[0] = 1
,其实这个也很好理解,当背包容量为0时,装满它的方法只有一个:什么也不装!
遍历顺序
- 物品正序,背包容量倒序(因为01背包每个物品只放一次),老生常谈
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
int sum = 0;
//算总和
for (int i = 0; i < nums.size(); i++) {
sum += nums[i];
}
//判断非法条件
if ((sum + target) % 2 != 0 || (sum + target) / 2 < 0)return 0;
target = (sum + target) / 2;
vector<int>dp (1020, 0);
dp[0] = 1;
//经典01背包
for (int i = 0; i < nums.size(); i++) {
for (int j = target; j >= nums[i]; j--) {
dp[j] += dp[j - nums[i]];
}
}
return dp[target];
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!