UVa 990 - Diving for Gold

  题目大意:一个潜水者去海底寻找金子,已知有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("\n");
34         printf("%d\n", 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\n", d[idx], v[idx]);
47         }
48     }
49     return 0;
50 }
View Code

 

posted @ 2013-09-07 10:34  xiaobaibuhei  阅读(217)  评论(0)    收藏  举报