题目大意:一个潜水者去海底寻找金子,已知有n个有金子的地点,分别给出他们的深度和价值。但是由于潜水者只有一瓶氧气,所以他只能在海底呆有限的时间,问他如何才能在这有限的时间里获得尽可能多的金子,并打印出方案。
dp中的0-1背包问题,得到最大值后根据dp数组可得到解决方案。采用“后i个物品”的规划方向可以使打印方案变得简单一点,详见《算法竞赛入门经典》9.3节。
1 #include <cstdio> 2 #include <iostream> 3 #include <vector> 4 using namespace std; 5 6 int d[35], v[35], dp[35][10000]; 7 vector<int> ans; 8 9 int main() 10 { 11 #ifdef LOCAL 12 freopen("in", "r", stdin); 13 #endif 14 int time, w; 15 bool first = true; 16 while (scanf("%d%d", &time, &w) != EOF) 17 { 18 int k = time / (3*w); 19 int n; 20 scanf("%d", &n); 21 for (int i = 1; i <= n; i++) 22 scanf("%d%d", &d[i], &v[i]); 23 for (int i = 0; i <= k; i++) 24 dp[n+1][i] = 0; 25 for (int i = n; i > 0; i--) 26 for (int j = 0; j <= k; j++) 27 { 28 dp[i][j] = dp[i+1][j]; 29 if (j >= d[i] && dp[i+1][j-d[i]]+v[i] > dp[i][j]) 30 dp[i][j] = dp[i+1][j-d[i]]+v[i]; 31 } 32 if (first) first = false; 33 else printf(" "); 34 printf("%d ", dp[1][k]); 35 ans.clear(); 36 for (int i = 1, j = k; i <= n; i++) 37 if (j >= d[i] && dp[i][j] == dp[i+1][j-d[i]]+v[i]) 38 { 39 ans.push_back(i); 40 j -= d[i]; 41 } 42 cout << ans.size() << endl; 43 for (int i = 0; i < ans.size(); i++) 44 { 45 int idx = ans[i]; 46 printf("%d %d ", d[idx], v[idx]); 47 } 48 } 49 return 0; 50 }