交大OJ 3021 有限背包(背包问题
2017-11-29 21:32
218 查看
有限背包
Description
大家都已经学过了01背包问题,现在这个问题稍微有一些变化:第i种物品可能有pi个,你可以选取任意个(小于pi)。给定背包容量V,求背包能达到的最大价值。
Input Format
第1行有2个整数N,V,表示要有N种物品,背包容量为V 第2到n+1行,每行三个整数pi, wi, ci,分别表示该种物品有pi个,每个物品体积ci,价值为wi
Output Format
输出一个数字, 表示背包能达到的最大价值。
Sample Input 1
3 9
1 2 3
2 3 4
3 4 5
Sample Output1
12
数据范围
对于80%的数据,1<=n<=1000,1<=m<=1000, 1<=sumP=p1+p2+…+pn<=2000 对于100%的数据,1<=N<=1000, 1<=m<=1000, 1<=pi<=1000
错解:
答案错误,错在代码块中加粗部分for (j = w[i]; j <=m; j++),顺序循环每次循环中可能c[i]被加了多余一次,没法达到每次循环c[i]只能用一次的目的(即:f[i]每个元素每次循环只能加一次c[i]),所以应该倒序循环!!!正解如下
正解:
对比博主前一条博客,无限背背包可进一步理解正序循环和逆序循环的区别
参考资料:
无限背包博客:http://blog.csdn.net/biwendong/article/details/78640648
Description
大家都已经学过了01背包问题,现在这个问题稍微有一些变化:第i种物品可能有pi个,你可以选取任意个(小于pi)。给定背包容量V,求背包能达到的最大价值。
Input Format
第1行有2个整数N,V,表示要有N种物品,背包容量为V 第2到n+1行,每行三个整数pi, wi, ci,分别表示该种物品有pi个,每个物品体积ci,价值为wi
Output Format
输出一个数字, 表示背包能达到的最大价值。
Sample Input 1
3 9
1 2 3
2 3 4
3 4 5
Sample Output1
12
数据范围
对于80%的数据,1<=n<=1000,1<=m<=1000, 1<=sumP=p1+p2+…+pn<=2000 对于100%的数据,1<=N<=1000, 1<=m<=1000, 1<=pi<=1000
错解:
#include <iostream> using namespace std; int max(int a, int b) { if (a > b) return a; else return b; } int main() { int n, m, p[1001], w[1001], v[1001], f[1001], count[1001]; int i, j, k; cin >> n >> m; for (i = 1; i <= n; i++) { cin >> p[i] >> w[i] >> v[i]; } for (k = 0; k <= m; k++) { f[k] = 0; } /*for (i = 1; i <= n; i++) { for (k = 0; k <=m; k++) { count[k] = 0; } for (j = w[i]; j <= m; j++) { if (count[j - w[i]] < p[i]) { f[j] = max(f[j - w[i]] + v[i], f[j]); if (f[j] == f[j - w[i]] + v[i]) count[j] = count[j - w[i]] + 1; } else if (f[j] == 0) { f[j] = f[j - 1]; count[j] = count[j - 1]; } else count[j] = count[j - 1]; } }*/ for (i = 1; i <= n; i++) { for (k = 1; k <= p[i]&&k<=m/w[i]; k++) { **for (j = w[i]; j <=m; j++)** { f[j] = max(f[j], f[j - w[i]] + v[i]); } } } cout << f[m]; return 0; }
答案错误,错在代码块中加粗部分for (j = w[i]; j <=m; j++),顺序循环每次循环中可能c[i]被加了多余一次,没法达到每次循环c[i]只能用一次的目的(即:f[i]每个元素每次循环只能加一次c[i]),所以应该倒序循环!!!正解如下
正解:
#include <iostream> #include <cstdio> using namespace std; int max(int a, int b) { if (a > b) return a; else return b; } int main() { int V, N, c[1001], w[1001], f[10001],p[1001]; scanf("%d", &N); scanf("%d", &V); int i, v; for (i = 1; i <= N; i++) { scanf("%d",&p[i]); scanf("%d", &c[i]); scanf("%d", &w[i]); } for (v = 0; v <= V; v++) { f[v] = 0; } for (i = 1; i <= N; i++) { for(int k=1;k<=p[i]&&k<=V/c[i];k++)//这里k有两个限制条件,既不能超过数量p[i],也不能超过背包容量V(k<=V/v[i]); for (v = V; v >=c[i]; v--) {//起点是c[i],倒序递减,每次循环中只能用一个c[i]; f[v] = max(f[v], f[v - c[i]] + w[i]);//这里通过递归f[v-c[i]]一定是最优解,如果加上w[i]权值比f[v]大,那么就是最优解。 } } printf("%d", f[V]);//完成递归以后f[V]就是最大权值 return 0; }
对比博主前一条博客,无限背背包可进一步理解正序循环和逆序循环的区别
参考资料:
无限背包博客:http://blog.csdn.net/biwendong/article/details/78640648
相关文章推荐
- 交大OJ 1272 写数游戏/背包问题
- 九度OJ 1455 珍惜现在,感恩生活 -- 动态规划(背包问题)
- 【背包+阈值优化】51Nod 1597 有限背包计数问题
- 九度OJ 1532 棋盘寻宝扩展 -- 动态规划【背包问题】
- 贪心法 南阳oj 背包问题
- 南阳OJ106-背包问题(贪心算法)
- 51Nod1597 有限背包计数问题
- 01 背包问题 cafeteria HPUOJ
- 1597 有限背包计数问题
- (有限物品背包问题) poj 1276 Cash Machine
- 南阳oj106 背包问题
- [DP]51 Nod 1597——有限背包计数问题
- nyoj106背包问题为模板解出杭电oj2187悼念512汶川大地震遇难同胞——老人是真饿了
- 南邮 OJ 1308 背包问题
- 【阈值优化+背包】51Nod1597[有限背包计数问题]题解
- 有限背包计数问题
- 交大OJ 1069 二哥的硬币(多重背包/单调队列)
- xynuoj 可分割背包问题 酒馆浪人的博客
- [51nod1597] 有限背包计数问题
- 南阳OJ 背包问题