01背包的路径全纪录
来源:互联网 发布:数据抽样方法 编辑:程序博客网 时间:2024/06/08 19:55
用DP求出 01背包的最大价值后该如何求得这条路径,就是有多少种选取情况下可以达到这个最大价值呢?
在本次百度之星的比赛中,有毒的1004让我好好思考了这个问题:
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>using namespace std;int dp[105][1005];int score[105], cost[105];bool re[105][105];int main(){ int CASE; scanf("%d", &CASE); for(int cas = 1; cas <= CASE; ++cas) { int pre, n; scanf("%d%d", &pre, &n); for(int i = 1; i <= n; ++i) scanf("%d%d", &score[i], &cost[i]); memset(dp, 0, sizeof(dp)); memset(re, 0, sizeof(re)); for(int i = 1; i <= n; ++i) { for(int j = pre; j >= cost[i]; --j) { if(dp[i - 1][j] <= dp[i - 1][j - cost[i]] + score[i]) { re[i][j] = 1; dp[i][j] = dp[i - 1][j - cost[i]] + score[i]; } else dp[i][j] = dp[i - 1][j]; } for(int j = cost[i] - 1; j >= 0; --j) dp[i][j] = dp[i - 1][j]; } int ans = dp[n][pre]; int sum = 10005; int sum_cnt = 0; int con[105]; for(int i = n; i >= 1; --i) for(int j = pre; j >= 0; --j) { if(dp[i][j] == ans && re[i][j]) { int tsum = 0; int cnt = 0; int tmp[105]; int x, y; for(x = i, y = j; x >= 1 && y > 0; x -= 1) { if(re[x][y]) { y -= cost[x]; tsum += x; tmp[cnt++] = x; } } if(y > 0) continue; //for(int t = cnt - 1; t >= 0; --t) //printf("%d%c", tmp[t], t == 0 ? '\n' : ' '); if(tsum < sum) { sum = tsum; sum_cnt = cnt; for(int t = 0; t < cnt; ++t) con[t] = tmp[t]; } else if(tsum == sum) { int ok = 0; for(int k = cnt - 1, t = sum_cnt - 1; k >= 0 && t >= 0; --t, --k) { if(con[t] != tmp[k]) { ok = con[t] < tmp[k] ? 0 : 1; break; } } if(ok == 1) { sum_cnt = cnt; for(int t = 0; t < cnt; ++t) con[t] = tmp[t]; } } } } sum = 0; for(int i = 0; i < sum_cnt; ++i) sum += cost[con[i]]; printf("Case #%d:\n", cas); printf("%d %d\n", ans, sum); for(int i = sum_cnt - 1; i >= 0; --i) printf("%d%c", con[i], i == 0 ? '\n' : ' '); } return 0;}
2017百度之星1004 度度熊的午饭时光
#include <iostream>#include <cstdio>#include <algorithm>#include <cstring>using namespace std;int dp[105][1005];int score[105], cost[105];bool re[105][1005];//一切问题的根源在于你的数组开小了int main(){ int CASE; scanf("%d", &CASE); for(int cas = 1; cas <= CASE; ++cas) { int pre, n; scanf("%d%d", &pre, &n); for(int i = 1; i <= n; ++i) scanf("%d%d", &score[i], &cost[i]); memset(dp, 0, sizeof(dp)); memset(re, 0, sizeof(re)); for(int i = 1; i <= n; ++i) { for(int j = pre; j >= cost[i]; --j) { if(dp[i - 1][j] <= dp[i - 1][j - cost[i]] + score[i]) { re[i][j] = 1; dp[i][j] = dp[i - 1][j - cost[i]] + score[i]; } else dp[i][j] = dp[i - 1][j]; } for(int j = cost[i] - 1; j >= 0; --j) dp[i][j] = dp[i - 1][j]; } int ans = dp[n][pre]; if(ans == 0) { printf("Case #%d:\n", cas); printf("0 0\n"); continue; } int sum = 10005; int sum_cnt = 0; int con[105]; for(int i = n; i >= 1; --i) for(int j = pre; j >= 0; --j) { if(dp[i][j] == ans && re[i][j]) { int tsum = 0; int cnt = 0; int tmp[105]; int x, y; for(x = i, y = j; x >= 1 && y > 0; x -= 1) { if(re[x][y]) { y -= cost[x]; tsum += x; tmp[cnt++] = x; } } if(y > 0) continue; //for(int t = cnt - 1; t >= 0; --t) //printf("%d%c", tmp[t], t == 0 ? '\n' : ' '); if(tsum < sum) { sum = tsum; sum_cnt = cnt; for(int t = 0; t < cnt; ++t) con[t] = tmp[t]; } else if(tsum == sum) { int ok = 0; for(int k = cnt - 1, t = sum_cnt - 1; k >= 0 && t >= 0; --t, --k) { if(con[t] != tmp[k]) { ok = con[t] < tmp[k] ? 0 : 1; break; } } if(ok == 1) { sum_cnt = cnt; for(int t = 0; t < cnt; ++t) con[t] = tmp[t]; } } } } sum = 0; for(int i = 0; i < sum_cnt; ++i) sum += cost[con[i]]; for(int i = 1; i <= n; ++i) { if(score[i] != 0 && cost[i] == 0) { con[sum_cnt++] = i; } } sort(con, con + sum_cnt); printf("Case #%d:\n", cas); printf("%d %d\n", ans, sum); for(int i = 0; i < sum_cnt; ++i) printf("%d%c", con[i], i == sum_cnt - 1 ? '\n' : ' '); } return 0;}
经过十几发的WA终于AC了这道有毒的题目,最后才发现原来一开始re数组开的是105*105,所以一直没有发现,天哪噜!!!
阅读全文
0 0
- 01背包的路径全纪录
- Uva624(记录路径的01背包)
- 记录路径的01背包问题
- 01背包路径输出
- 01背包+记录路径
- 01背包查找路径
- 01背包、完全背包、多重背包问题的C++实现及路径记录
- 记录路径的背包问题
- hdu2126Buy the souvenirs (01背包+记录路径的种数)
- POJ1853 Cat (变形与记录路径的01背包)
- uva624 CD (01背包+路径的输出)
- UVA 624 CD 【记录路径式的01背包】
- UVA 624CD(打印路径的01背包)
- 01背包&&打印路径(hdu6083)度度熊的午饭时光
- 01背包+打印路径 hdu6083度度熊的午饭时光
- 01背包之打印路径
- uva 01背包记录路径
- 01背包记录路径)
- 牛客网-做题笔记
- 《机器学习》读书笔记 3 第1章 绪论
- HDU 6076 Security Check (DP, 2017 Multi-Univ Training Contest 4)
- php502问题解决:recv() failed (104: Connection reset by peer) while reading response header from upstream
- Android学习笔记——Git使用技巧
- 01背包的路径全纪录
- LVM
- Google算法题:最多有k个不同字符的最长子字符串
- 使用QUnit测试JavaScript
- mysql 数据库 sql mode 的研究与整理
- 快速幂-竞赛算法用法-和-例题详解---Hayden's Blog.
- USB驱动之xhci
- Mysql数据类型和运算符学习
- 内存的管理艺术(基于C语言)1