zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    jquery on()方法绑定多个选择器,多个事件
    html中常用的特殊符号(转)
    jQuery自定义动画,animate()包装器方法
    纯CSS下拉菜单
    DIV水平居中的几种方法
    OOXML是什么
    Chrome网络工具总结
    Content-Length错误导致的Servlet下载文件失败问题
    Fiddler操作总结
    WinSCP上传下载过滤指定目录和文件
  • 原文地址:https://www.cnblogs.com/Griselda/p/3027132.html
Copyright © 2011-2022 走看看