Cow Exhibition------变种01背包

原题
题目大意:一共有n头牛,每头牛都有个值s[i],f[i]。请从中取一部分牛出来,使得这部分牛的s之和S不为负数,f之和F不为负数,且此时的S+F最大,请输出S+F的值。

解题思路:是后来看博客补的,这里使用的是dp的解法,不过,这里dp[i],i储存的是s[i]当前的总和。
所以,这样dp表达式很容易就可以出来dp[i]=max(dp[i],dp[i-s[j]]+f[j])
但是重点的不是这个,是次序,因为每个牛只能使用一次,所以s[i]是正是负的顺序是不一样的,其实都是为了保证最新得到的dp不会受到此次dp之前的任何dp的影响(因为已经更新过的dp都受到了这头牛的影响,而一头牛只可以影响一次)。

注意:
1:当s[i]和f[i]都是负数时,直接continue,没什么好说的
2:更新当前的dp的前提时该dp曾经被用过,
3: 为了得到负数,可以把0节点往前推,使得dp[100000]=0;

#include<cstdio>
#include<iostream>
using namespace std;
const int MX=2e5+9;
const int inf=0x3f3f3f3f;
int dp[MX+1],n,s[MX],f[MX];
int main()
{
    freopen("input.txt","r",stdin);
    while( ~scanf("%d",&n) ){
        for( int i=1 ; i<=n ; i++ )
            scanf("%d %d ",&s[i],&f[i]);
        for( int i=0 ; i<=MX ; i++ )
            dp[i]=-inf;
        dp[100000]=0;
        for( int i=1 ; i<=n ; i++ ){
            if( s[i]<=0 && f[i]<=0 )
                continue;
            if( s[i]>0 ){
                for( int j=MX ; j>=s[i] ; j-- )   // 最新的dp不会受到刚刚dp完的影响
                    if( dp[j-s[i]]>-inf )   // 使用这个dp一定要这个dp曾经被使用过
                        dp[j]=max(dp[j],dp[j-s[i]]+f[i]);
            }
            else {
                for( int j=s[i] ; j<=MX+s[i] ; j++ )   // 同上
                    if( dp[j-s[i]]>-inf )
                        dp[j]=max(dp[j],dp[j-s[i]]+f[i]);
            }
        }
        int ans=-inf;
        for( int i=100000 ; i<=MX ; i++ )
            if( dp[i]>=0 )    // 因为s的总和大于等于0,f的总和也要大于等于0,所以dp必须取>=0的,
                ans=max(ans,i-100000+dp[i]);
        printf("%d\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值