牛客网 TaoTao要吃鸡 ( 0/1背包变形 )

Posted rubbishes

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客网 TaoTao要吃鸡 ( 0/1背包变形 )相关的知识,希望对你有一定的参考价值。

题意 : 题目链接

 

分析 : 

如果没有 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背包变形 )的主要内容,如果未能解决你的问题,请参考以下文章

多校寒训TaoTao要吃鸡dp(未完成)

Tao Tao要吃鸡

牛客网_2018年全国多校算法寒假训练营练习比赛(第一场)_部分题解

牛客网青蛙变态跳台阶问题

讨“动态规划“檄

讨“动态规划“檄