目录
LintCode 炼码物品大小不重复的填满背包的方案数
LintCode 炼码 物品大小存在重复情况
LintCode 炼码不重复的组合个数
完全背包_牛客题霸_牛客网
描述给出 n 个物品, 以及一个数组, nums[i]
代表第i
个物品的大小, 保证大小均为正数并且没有重复, 正整数 target
表示背包的大小, 找到能填满背包的方案数。每一个物品可以使用无数次(完全背包由前往后)
class Solution {
public:
int backPackIV(vector &nums, int target) {
// write your code here
int n = nums.size();
vector dp(target+1);
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];
}
};
给出 n 个物品, 以及一个数组, nums[i]
代表第i个物品的大小, 保证大小均为正数, 正整数 target
表示背包的大小, 找到能填满背包的方案数。每一个物品只能使用一次(0-1背包由后往前)
class Solution {
public:
/**
* @param nums: an integer array and all positive numbers
* @param target: An integer
* @return: An integer
*/
int backPackV(vector &nums, int target) {
// Write your code here
vector dp(target + 1);
dp[0] = 1;
for (auto a : nums) {
for (int i = target; i >= a; --i) {
dp[i] += dp[i - a];
}
}
return dp.back();
}
};
class Solution {
public:
int backPackVI(vector &nums, int target) {
// write your code here
vector dp(target+1);
dp[0] =1;
for (int i = 1; i <= target; i++) {
for (int num : nums) {
if (num <= i) {
dp[i] += dp[i - num];
}
}
}
return dp[target];
}
};
【模板】01背包_牛客题霸_牛客网描述
你有一个背包,最多能容纳的体积是V。
现在有n个物品,第i个物品的体积为vivi ,价值为wiwi。
(1)求这个背包至多能装多大价值的物品?
(2)若背包恰好装满,求至多能装多大价值的物品?
输入描述:
第一行两个整数n和V,表示物品个数和背包体积。
接下来n行,每行两个数vivi和wiwi,表示第i个物品的体积和价值。
1≤n,V,vi,wi≤10001≤n,V,vi,wi≤1000
输出描述:
输出有两行,第一行输出第一问的答案,第二行输出第二问的答案,如果无解请输出0。
#include
using namespace std; #include int A[1005]; int w[1005]; int main() { int n,m; cin>>n>>m; for(int i = 0; i < n; i++) cin>>A[i]>>w[i]; vector a(m+1, 0); vector b(m+1, -0x3f3f3f3f); b[0] = 0; for(int i = 0; i < n; i++) { for(int j = m; j >=A[i]; j--) { a[j] = max(a[j], a[j-A[i]]+w[i]); b[j] = max(b[j], b[j-A[i]]+w[i]); } } cout< 0 ? b[m] : 0; cout<
描述
你有一个背包,最多能容纳的体积是V。
现在有n种物品,每种物品有任意多个,第i种物品的体积为vivi ,价值为wiwi。
(1)求这个背包至多能装多大价值的物品?
(2)若背包恰好装满,求至多能装多大价值的物品?
数据范围: 1≤v,vi,wi≤1000 1≤v,vi,wi≤1000
示例1
输入:6,2,[[5,10],[3,1]]
返回值:[10,2]
示例2
输入:8,3,[[3,10],[9,1],[10,1]]
返回值:[20,0]
说明:无法恰好装满背包。
示例3
输入:13,6,[[13,189],[17,360],[19,870],[14,184],[6,298],[16,242]]
返回值:[596,189]
说明:可以装5号物品2个,达到最大价值298*2=596,若要求恰好装满,只能装1个1号物品,价值为189.
问题1和问题2的求解过程基本一致 ,不同的是在动态规划初始化数组时,在求解问题1时其所对应的动态规划数组全部为0,在求解问题2时其所对应的动态规划数组只有第一个元素为0其余的为负无穷。之所以将动态规划数组里的元素设为负无穷,是为了进行阻断。在从前至后推进时如果在填充了当前元素后还有剩余空间,那么之前扫描过的其他元素若不能恰好填满剩余空间,则这个元素将无法被成功填充(表征为:负无穷加上一个常数还是负无穷),即这种情况将会被阻断。
class Solution { public: /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param v int整型 * @param n int整型 * @param nums int整型vector
> * @return int整型vector */ vector knapsack(int m, int n, vector >& nums) { // write code here vector dp(m+1, 0); vector b(m+1, INT_MIN); b[0] = 0; vector v(n); vector w(n); for(int i = 0; i < n; ++i) { v[i] = (nums[i][0]); w[i] = (nums[i][1]); } for(int i = 0; i < n; ++i) { for(int j = v[i]; j <= m; j++) { dp[j] = max(dp[j], dp[j-v[i]]+w[i]); b[j] = max(b[j], b[j-v[i]]+w[i]); } } vector res(2); res[0] = dp[m]; res[1] = b[m]>0?b[m]:0; return res; } };