zoukankan      html  css  js  c++  java
  • 牛客网 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
    ", ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    1、如何使用Azure Rest API创建虚拟机
    Ansible---2的Roles使用
    linux下的shell脚本
    生成器 yield和协程
    xshell
    markdown的使用
    加密
    Hbuilder打包app
    尾递归
    jupyter
  • 原文地址:https://www.cnblogs.com/qwertiLH/p/8536617.html
Copyright © 2011-2022 走看看