POJ 2184 Cow Exhibition(01背包)

Description
有一些奶牛,他们有一定的s值和f值,这些值有正有负,最后让保证s的和为非负且f的和为非负的情况下,s+f的最大值
Input
第一行为奶牛数量n,之后n行每行两个整数表示对应奶牛的s和f值
Output
输出保证s和非负f和非负时的s+f的最大值
Sample Input
5
-5 7
8 -6
6 -3
2 1
-8 -5
Sample Output
8
Solution
将s+100000看作重量,f看作价值,问题转化为01背包问题,最后取dp[i]+i-100000(100000 <=i<=200000,dp[i]>=0)的最大值即可,注意由于01背包省略第一维后为避免后效性,内层循环都是逆着推的,因此s值为负时内层循环方向与s值为正时相反
Code

#include
#define maxn 100000
#define INF 1<<30
#define max(x,y) ((x)>(y)?(x):(y))
int dp[2*maxn+10],n,s[101],f[101];
int main()
{
    while(~scanf("%d",&n))
    {
        for(int i=1;i<=n;i++)
            scanf("%d%d",&s[i],&f[i]);
        for(int i=0;i<=2*maxn;i++)//初始化 
            dp[i]=-INF;
        dp[maxn]=0;
        for(int i=1;i<=n;i++)//01背包 
        {
            if(s[i]<0&&f[i]<0)//剪枝 
                continue;
            if(s[i]>=0)
            {
                for(int j=2*maxn;j>=s[i];j--)
                    if(dp[j-s[i]]>-INF)
                        dp[j]=max(dp[j],dp[j-s[i]]+f[i]);
            }
            else
            {
                for(int j=s[i];j<=2*maxn+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=maxn;i<=2*maxn;i++)//满足s和非负 
            if(dp[i]>=0)//满足f和非负 
                ans=max(ans,dp[i]+i-maxn);//更新s+f最大值 
        printf("%d\n",ans);
    }
    return 0;
} 

你可能感兴趣的:(POJ,背包问题)