牛客網 TaoTao要吃雞 ( 0/1背包變形 )
阿新 • • 發佈:2018-03-10
tar %d 如何 將不 bug 存在 分享 lose ems
題意 : 題目鏈接
分析 :
如果沒有 BUG (即 h == 0 的時候)就是一個普通的 0 / 1 背包
需要討論一下 h != 0 的情況
此時有就相當於有物品是有特權的
而且背包裝有特權的物品根據題目的要求是應當最後裝的
也就是說特權物品裝完之後背包將不再可裝
所以特權物品肯定是只有一個的
數據量並不大,所以可以去枚舉這個特權物品
那麽如何知道在 沒有裝特權物品 之前的最佳選擇方案?
答案就是用最小的可剩空間留給特權物品,然後其他空間去跑 0/1 背包
最小的可剩空間當然就是 h + m - 1,只留一個單位空間給特權物品即可
最後除了枚舉的物品,其他的物品去跑背包容量為 h + m - 1 的 0/1 背包
#include<bits/stdc++.h> using namespace std; const int maxn = 1e2 + 10; int w[maxn], v[maxn], dp[maxn<<1]; int C, n, m, h; int main(void) { while(~scanf("%d", &n) && n){ scanf("%d %d", &m, &h), C = m + h; for(int i=1; i<=n; i++) scanf(View Code"%d %d", &w[i], &v[i]); int ans = 0; memset(dp, 0, sizeof(dp)); for(int i=1; i<=n; i++) for(int j=C; j>=w[i]; j--) dp[j] = max(dp[j], dp[j-w[i]] + v[i]); ans = dp[C]; if(h != 0){///有 BUG 存在 for(int k=1; k<=n; k++){///枚舉特權物品 memset(dp, 0, sizeof(dp));///記得初始化 for(int i=1; i<=n; i++){ if(i == k) continue;///特權物品不在 0/1 背包過程中 for(int j=C-1; j>=w[i]; j--){ dp[j] = max(dp[j], dp[j-w[i]] + v[i]); } } ans = max(ans, dp[C-1] + v[k]);///最後維護最優值 } } printf("%d\n", ans); } return 0; }
牛客網 TaoTao要吃雞 ( 0/1背包變形 )