• 2018年全国多校算法寒假训练营练习比赛(第二场)B


    链接:https://www.nowcoder.com/acm/contest/74/B
    来源:牛客网

    题目描述


    Taotao的电脑带不动绝地求生,所以taotao只能去玩pc版的荒野行动了,
    和绝地求生一样,游戏人物本身可以携带一定重量m的物品,装备背包
    之后可以多携带h(h为0代表没有装备背包)重量的东西。玩了几天
    taotao发现了一个BUG,当装备背包之后,如果可携带重量没有满,就
    可以拿一个任意重的东西。(解释看样例)有一天taotao空降到了一个
    奇怪的岛上,岛上有n件装备,每个装备都有重量Wi和威力值Vi,但taotao
    不认识这些装备,所以他来求助你,挑选威力最大的装备,帮助他吃鸡。
    

    输入描述:

    本题有多组输入(小于10),当n=0时结束输入。
    第一行输入n,m,h。n,m,h为整数,并且0<=n,m,h<=100,
    接下来n行,每行输入第i个物品的物品的重量Wi和威力值Vi。0<=Wi,Vi<=100.

    输出描述:

    输出最大威力值,每组输出一行。
    示例1

    输入

    3 3 3
    2 3
    3 2
    2 3
    0

    输出

    8

    说明

    可携带的总重量为6,当拿了前两件装备,此时容量为5/6,还可以再拿第三件物品。

    题解

    背包$dp$。

    这题有个坑点,只有当$h$不为$0$的时候,才有$bug$。

    即:$h$为$0$时,直接做$01$背包;$h$不为$0$时,可以枚举哪一个最后放进去,然后去除这个做$01$背包再算答案。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 200 + 10;
    int n, m, h;
    int dp[maxn];
    int w[maxn], v[maxn];
    
    int main() {
      while(~scanf("%d", &n)) {
        if(n == 0) break;
        scanf("%d%d", &m, &h);
        memset(dp, -1, sizeof dp);
        dp[0] = 0;
        for(int i = 1; i <= n; i ++) {
          scanf("%d%d", &w[i], &v[i]);
          if(w[i] == 0) dp[0] += v[i];
        }
        int ans = 0;
        if(h == 0) {
          for(int i = 1; i <= n; i ++) {
            if(w[i] == 0) continue;
            if(v[i] == 0) continue;
            for(int j = m; j >= w[i]; j --) {
              if(dp[j - w[i]] == -1) continue;
              dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
            }
          }
          for(int i = 0; i <= m; i ++) {
            ans = max(ans, dp[i]);
          }
        } else {
          ans = dp[0];
          for(int t = 1; t <= n; t ++) {
            if(w[t] == 0 || v[t] == 0) continue;
            for(int i = 1; i <= m + h; i ++) {
              dp[i] = -1;
            }
            for(int i = 1; i <= n; i ++) {
              if(w[i] == 0 || v[i] == 0) continue;
              if(i == t) continue;
              for(int j = m + h; j >= w[i]; j --) {
                if(dp[j - w[i]] == -1) continue;
                dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
              }
            }
            for(int i = 0; i <= m + h; i ++) {
              ans = max(ans, dp[i]);
            }
            for(int i = 0; i <= m + h - 1; i ++) {
              if(dp[i] == -1) continue;
              ans = max(ans, dp[i] + v[t]);
            }
          }
        }
        printf("%d
    ", ans);
      }
      return 0;
    }
    
  • 相关阅读:
    插入排序
    排序算法结构表
    两个数字交换的四种方法
    LRU算法实现
    虚拟用户的配置
    【转】Linux查看CPU和内存使用情况
    Linux 多线程开发
    【转】RTSP流理解
    【转】DynDNS使用随笔
    【转】使用 udev 高效、动态地管理 Linux 设备文件
  • 原文地址:https://www.cnblogs.com/zufezzt/p/8372340.html
Copyright © 2020-2023  润新知