Hlg 1740 DP求路径且按最小字典序输出.cpp

题意:

  给出n个石头的重量和得分,有一个为m的背包,问在m个背包里能装的最大得分是多少,并要求输出装入的石子编号..

  如果有多个解则输出字典序最小的..

 

思路:

  这个在背包九讲后面有提及..

  主要是用一个二维数组path[i][j]表示当体积为j的时候第i件物品是否有被装入..

  最后用一次循环根据if(path[i][tv]) {

                ans[cnt++] = i;

                tv -= v[i];

            }

  就可以求出路径并保存在ans里面了..

Tips:

  注意找的时候应该是从i = n往前遍历..

  而输出的时候应该是cnt~0

 

  做这道题的过程中遇到一个问题就是:如果我是用二维数组来求01背包,那代码应该是

  

二维数组求01背包
 1 #include <stdio.h>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 int v[110], w[110];
 7 int  dp[101][1010], path[100010], ans[110];
 8 int main()
 9 {
10     freopen("in.in", "r", stdin);
11     int T, n, m;
12     int cnt, sum;
13     scanf("%d", &T);
14     while(T--) {
15         scanf("%d %d", &n, &m);
16         memset(dp, 0, sizeof(dp));
17         memset(path, 0, sizeof(path));
18         cnt = 0;
19         int res = 0;
20         for(int i = 1; i <= n; ++i)
21             scanf("%d %d", &v[i], &w[i]);
22         for(int i = 1; i <= n; ++i) {
23             for(int j = m; j >=v[i]; --j) {
24                 dp[i][j] = max(dp[i-1][j-v[i]]+w[i], dp[i-1][j]);
25             }
26             for (int j=v[i]-1;j>=0; j--)dp[i][j] = dp[i-1][j];
27         }
28         printf("%d\n", dp[n][m]);
29     }
30     return 0;
31 }

 

  因为i+1的体积可能比i小..

  但是每次更新都是从v[i]~V..

  所以应该把0~v[i]都加到dp[i][0~v[i]]里..

 

 

Code:

View Code
 1 #include <stdio.h>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 int v[110], w[110], dp[100010], ans[110];
 7 bool path[110][10010];
 8 int main()
 9 {
10    // freopen("in.txt", "r", stdin);
11     int T, n, m;
12     int cnt, sum;
13     scanf("%d", &T);
14     while(T--) {
15         scanf("%d %d", &n, &m);
16         memset(dp, 0, sizeof(dp));
17         memset(path, 0, sizeof(path));
18         cnt = 0;
19         for(int i = 1; i <= n; ++i)
20             scanf("%d %d", &v[i], &w[i]);
21 
22         for(int i = 1; i <= n; ++i) {
23             for(int j = m; j >= v[i]; --j) {
24                 int t = dp[j];
25                 dp[j] = max(dp[j-v[i]]+w[i], dp[j]);
26                 path[i][j] = dp[j] == t?false:true;
27             }
28         }
29         int tv = m;
30         for(int i = n; i > 0; --i)
31             if(path[i][tv]) {
32                 ans[cnt++] = i;
33                 tv -= v[i];
34             }
35 
36         printf("%d\n", dp[m]);
37         for(int i = cnt-1; i >= 0; --i)
38             printf("%d%c", ans[i], i == 0?'\n':' ');
39     }
40     return 0;
41 }

 

链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProblem&problem_id=1740

posted @ 2013-04-17 21:32  Griselda.  阅读(247)  评论(0编辑  收藏  举报