1. 程式人生 > >2018年全國多校算法寒假訓練營練習比賽(第二場)B - TaoTao要吃雞

2018年全國多校算法寒假訓練營練習比賽(第二場)B - TaoTao要吃雞

esc spa scanf namespace scribe sin bold ans 最大

鏈接: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\n", ans);
  }
  return 0;
}

2018年全國多校算法寒假訓練營練習比賽(第二場)B - TaoTao要吃雞