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

  • 相关阅读:
    HDU 4611 Balls Rearrangement 数学
    Educational Codeforces Round 11 D. Number of Parallelograms 暴力
    Knockout.Js官网学习(简介)
    Entity Framework 关系约束配置
    Entity Framework Fluent API
    Entity Framework DataAnnotations
    Entity Framework 系统约定配置
    Entity Framework 自动生成CodeFirst代码
    Entity Framework CodeFirst数据迁移
    Entity Framework CodeFirst尝试
  • 原文地址:https://www.cnblogs.com/Griselda/p/3027132.html
Copyright © 2011-2022 走看看