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

你可能感兴趣的:(cpp)