牛客网 B-TaoTao要吃鸡 01背包

链接:https://www.nowcoder.com/acm/contest/74/B

来源:牛客网

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

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.

输出描述:

输出最大威力值,每组输出一行
这道题目考察的是 01 背包,和 01 背包不同的是,这里的容量不确定,要分类:
背包容量为 0 , 总容量为手上的容量,直接 01 背包;
背包容量不为0,因为  0 <= 物品威力 <= 100 ,都是整数。所以如果有的物品威力为 0 , 可能为了故意不装满背包而最后选了这件物品,就不是最大值。所以,要考虑最后不拿一件物品的情况。
      最后不拿一件物品,总容量就是 m+h ,最大值是 01 背包; 
      最后拿一件物品,总容量上限是 m+h-1 , 最大值是 01 背包+最后拿的那件物品的威力 ;
多种情况取最大值。

#include <iostream>  
#include <cstdio>  
#include <cstring>  
using namespace std ;  
int dp[202] , cost[101] , value[101] ;  
  
int main(){  
    int n , m , h , i , j , k ;  
    while( cin >> n && n ){  
        cin >> m >> h ;  
        for( i = 1 ; i <= n ; ++i )  
            cin >> cost[i] >> value[i] ;  
        memset( dp , 0 , sizeof( dp ) ) ;  
        if( h == 0 ){  
            for( i = 1 ; i <= n ; ++i )  
                for( j = m ; j >= cost[i] ; --j )   // 从 m 开始递减,避免重复,不懂先打表  
                    dp[j] = max( dp[j] , dp[j-cost[i]] + value[i] ) ;   
            printf( "%d\n" , dp[m] ) ;           // 最大容量为 m 时可以选择的最大威力的装备  
        }               
        else{
            for( int i = 1 ; i <= n ; ++i )           
                for( int j = m+h ; j >= cost[i] ; --j )  
                    dp[j] = max( dp[j] , dp[j-cost[i]] + value[i] ) ;  // 如果最后不选择带一件物品  
            int ans = dp[m+h] ;                  
            for( k = 1 ; k <= n ; ++k ){       // 枚举 n 件物品,如果不选这件物品,而是最后带上任意重的那件  
                memset( dp , 0 , sizeof( dp ) ) ;     // 每次 01 背包都要清空  
                for( i = 1 ; i <= n ; ++i )  
                    if( i != k )               // 暂且不选第 k 件  
                        for( j = m+h-1 ; j >= cost[i] ; --j )    // 只有当背包没装满,也就是背包的容量最大是 m+h-1   
                                dp[j] = max( dp[j] , dp[j-cost[i]] + value[i] ) ;  
                ans = max( ans , value[k] + dp[m+h-1] ) ;  // 最后背包没装满,带上第 k 件,加上背包和手可以选择的最大威力装备  
            }  
            cout << ans << endl ;  
        }    
            
    }  
    return 0 ;  
}  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值