//此题有助于理解滚动数组里面内存循环的顺序,当求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;
}
poj2184
最新推荐文章于 2023-03-28 19:58:38 发布