2018年全國多校算法寒假訓練營練習比賽(第二場)B - TaoTao要吃雞
阿新 • • 發佈:2018-01-28
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要吃雞