poj2184

//此题有助于理解滚动数组里面内存循环的顺序,当求dp[j]时,默认dp[j-w[i]]是dp[i-1][j-w[i]]这就要求在求dp[j]之前,dp[j-w[i]]不能改变(如果更改了,那么dp[j]就是用的更新
//过的值。如果w[i]为正,那么j-w[i]<w[i]所以从大到小,先访问w[i]再访问j-w[i](如果先算dp[j-w[i]]那么它如果被更新,dp[j]就错了)如果w[i]为负,j-w[i]大于,从小到大

#include <stdio.h>//我的大概思路就是将智商当作是重量,幽默(这是什么鬼)当作是价值,然后碰到智商小于0的就将其加上题目中的最大值,使其一定为正,然后开始背包
#include <string.h>
int max(int a,int b)
{
    return a>b?a:b;
}
 int main()
 {
     int i,j,n,ans;
     int dp[210005];
     int w[21000];//智商(理解为重量)
     int v[21000];//(理解为价值)
     scanf("%d",&n);
     for (i=1;i<=n;i++)
        scanf("%d%d",&w[i],&v[i]);
       for (i=0;i<=200000;i++)
        dp[i]=-999999;
        dp[100000]=0;
        for (i=1;i<=n;i++)
        {
            if ((w[i]<0)&&(v[i]<0))
                continue;//剪枝,如果都小肯定不用考虑
            else
             if (w[i]>0)
            {
                for (j=200000;j>=w[i];j--)
                if (dp[j-w[i]]>-999999)
                dp[j]=max(dp[j],dp[j-w[i]]+v[i]);//因为w[i]为正,所以j>j-w[i],当dp[j]未修改时,要保证dp[j-w[i]]也没有修改(因为dp[j]其实质是dp[i-1][j],就是之前的那个数),要保证先访问dp[j],再访问dp[j-w[i]].
            }
            else
            {
                for (j=0;j<=200000+w[i];j++)
                if (dp[j-w[i]]>-999999)
                dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
            }

        }
        ans=-99998;
        for (i=100000;i<=200000;i++)
          {
            if(dp[i]>=0)
                ans = max(ans,dp[i]+i-100000);
        }
        printf("%d\n",ans);

        return 0;
 }



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值