题目链接: http://bestcoder.hdu.edu.cn/contests/contest_showproblem.php?cid=774&pid=1004
题目大意: 一个0-1背包, 需要输出路径
解题思路: 0-1背包很好求, 输出路径以前没有做过.......就是记录更新位置, 然后通过数组的跳跃间距求出到底取的是哪些点......
代码: 自己代码, 没AC, 是什么玄学BUG, 我也懒得改了
#include <iostream> #include <cstdio> #include <string> #include <vector> #include <map> #include <cstring> #include <iterator> #include <cmath> #include <algorithm> #include <stack> #include <deque> #include <map> #define lson l, m, rt<<1 #define rson m+1, r, rt<<1|1 const int maxn = 1e3 + 100; using namespace std; //const int INF = 0x3fffffff; int score[maxn]; int cost[maxn]; int dp[maxn][maxn]; // 前i个花费<=j时的最高得分 int vis[maxn][maxn]; int temp[maxn]; int cnt; int main() { int t; scanf( "%d", &t ); for( int cases = 1; cases <= t; cases++ ) { cnt = 0; int B; int N; scanf( "%d%d", &B, &N ); for( int i = 1; i <= N; i++ ) { scanf( "%d%d", score+i, cost+i ); } memset(dp, 0, sizeof(dp)); memset(vis, 0, sizeof(vis)); if( N == 0 || B == 0 ) { printf( "Case #%d: ",cases ); printf( "0 0 " ); continue; } for( int i = 1; i <= N; i++ ) { for( int j = B; j >= 0; j-- ) { dp[i][j] = dp[i-1][j]; if( j >= cost[i] ) { if( dp[i-1][j-cost[i]]+score[i] > dp[i][j] ) { dp[i][j] = dp[i-1][j-cost[i]]+score[i]; vis[i][j] = 1; } } } } int ans = 0; int i = N, j = B; while (i > 0 && j > 0) { if (vis[i][j] == 1) { ans += cost[i]; j -= cost[i]; } i--; } printf( "Case #%d: ", cases ); printf( "%d %d ", dp[N][B], ans ); i = N, j = B; while (i > 0 && j > 0) { if (vis[i][j] == 1) { temp[cnt++] = i; j -= cost[i]; } i--; } sort( temp, temp + cnt); for( int i = 0; i < cnt; i++ ) { if( i == 0 ) printf( "%d", temp[i] ); else printf( " %d", temp[i] ); } printf( " " ); } return 0; }
徐文栋的AC代码:
#include <bits/stdc++.h> using namespace std; typedef pair<int, int> pii; const int maxn = 110; const int maxm = 1010; int m, n; int v[maxn], w[maxn]; int f[maxm]; int path[maxn][maxm]; vector<int> tmp; signed main() { // freopen("in", "r", stdin); int T, _ = 1; scanf("%d", &T); while(T--) { memset(path, 0, sizeof(path)); memset(f, 0, sizeof(f)); tmp.clear(); scanf("%d%d",&m,&n); for(int i = 1; i <= n; i++) { scanf("%d%d",&v[i], &w[i]); } for(int i = 1; i <= n; i++) { for(int j = m; j >= w[i]; j--) { if(f[j] < f[j-w[i]]+v[i]) { f[j] = f[j-w[i]] + v[i]; path[i][j] = 1; } } } printf("Case #%d: ", _++); int tot1 = 0, tot2 = 0; for(int i = n, j = m; i >= 1; i--) { if(path[i][j]) { tot1 += v[i]; tot2 += w[i]; tmp.push_back(i); j -= w[i]; } } printf("%d %d ", tot1, tot2); sort(tmp.begin(), tmp.end()); for(int i = 0; i < tmp.size(); i++) { printf("%d%c", tmp[i], i==tmp.size()-1?' ':' '); } } return 0; }
思考: 自己只会纯裸的0-1背包, 真的菜, 通过这道题又补了自己的知识点, 以后还是通过做题锻炼自己的思维,再补自己的知识点