目录
兑换零钱(二)_牛客题霸_牛客网(完全背包)
494. 目标和(0-1背包)
分割等和子集_牛客题霸_牛客网
兑换零钱(二)_牛客题霸_牛客网(完全背包)
描述
给定一个整数数组 nums 表示不同数额的硬币和一个正整数 target 表示总金额,请你计算并返回可以凑出总金额的的组合数。如果凑不出 target 则返回 0。
状态转移方程的推导就是利用上面,发现当背包容量为1的时候有dp[4]种方法可以凑出容量为5的方法数……最后发现dp[5]就等于其他dp[j-nums[i]]之和
初始化要设置第一个元素为1,比如
int change(int target, vector<int>& nums) {
// write code here
int n = nums.size();
vector<int> dp(target+1, 0);
dp[0] = 1;
for(int i = 0; i < n; ++i) // 物品
{
for(int j = nums[i]; j <= target; ++j) // 背包
{
dp[j] += dp[j-nums[i]];
}
}
return dp[target];
}
总结:
1、判断是01背包还是完全背包
2、组合数的状态转移方程都为dp[j] += dp[j-nums[i]]
3、如果求的是组合数就先进行遍历物品,再遍历背包
(因为物品从前到后进行拿取,有着顺序,不会重复)
如果求得是排列数先遍历背包在遍历物品
494. 目标和(0-1背包)
给你一个整数数组 nums 和一个整数 target 。
向数组中的每个整数前添加 '+' 或 '-' ,然后串联起所有整数,可以构造一个 表达式 :
例如,nums = [2, 1] ,可以在 2 之前添加 '+' ,在 1 之前添加 '-' ,然后串联起来得到表达式 "+2-1" 。
返回可以通过上述方法构造的、运算结果等于 target 的不同 表达式 的数目。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/target-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。示例 1:
输入:nums = [1,1,1,1,1], target = 3
输出:5
解释:一共有 5 种方法让最终目标和为 3 。
-1 + 1 + 1 + 1 + 1 = 3
+1 - 1 + 1 + 1 + 1 = 3
+1 + 1 - 1 + 1 + 1 = 3
+1 + 1 + 1 - 1 + 1 = 3
+1 + 1 + 1 + 1 - 1 = 3来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/target-sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
1、判断是01背包问题 (从后往前)
2、组合数使用 dp[j] += dp[j-nums[i]];
3、不同的组合数 (则使用先物品再背包)
class Solution {
public:
int findTargetSumWays(vector<int>& nums, int target) {
int add = 0;
for(auto &e : nums)
{
add += e;
}
if(add+target<0 || (add+target)%2 == 1)return 0;
int left = (add+target)/2;
vector<int> dp(left+1, 0);
dp[0] = 1;
for(int i = 0; i < nums.size(); ++i)
{
for(int j = left; j >= nums[i]; --j)
{
dp[j] += dp[j-nums[i]];
}
}
return dp[left];
}
};
分割等和子集_牛客题霸_牛客网
描述
给定一个只包含正整数的数组 nums ,请问能否把这个数组取出若干个数使得取出的数之和和剩下的数之和相同。
数据范围: 1≤n≤500 1≤n≤500 , 数组中的元素满足 1≤numsi≤100 1≤numsi≤100
输入描述:
第一行输入一个正整数 n ,表示数组 nums 的长度。
第二行输入 n 个正整数,表示数组中的值。
输出描述:
如果满足题目条件,输出 true ,否则输出 false
1、0-1背包问题
2、dp[j] += dp[j-nums[i]]
3、重不重复无所谓,先背包先物品都行
#include <iostream> using namespace std; #include<vector> int main() { int n; cin>>n; vector<int> nums(n); for(int i = 0; i < n; i++)cin>>nums[i]; int add = 0; for(auto &e : nums) { add+=e; } if(add%2==1) { cout<<"false"<<endl; return 0; } int left = add/2; vector<int> dp(left+1); dp[0] = 1; for(int i = 0; i < nums.size(); i++) { for(int j = left; j >= nums[i]; j--) { dp[j] += dp[j-nums[i]]; } } if(dp[left]==0) cout<<"false"<<endl; else cout<<"true"<<endl; return 0; } // 64 位输出请用 printf("%lld")