1. 程式人生 > >牛客網 TaoTao要吃雞 ( 0/1背包變形 )

牛客網 TaoTao要吃雞 ( 0/1背包變形 )

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(
"%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; }
View Code

牛客網 TaoTao要吃雞 ( 0/1背包變形 )