题目链接:https://vjudge.net/problem/POJ-2184
01背包问题的变形。将S当做重量,F当做价值。但注意此时S可能有负数且-1000<=Si<=1000,且N<=100。所以可以考虑将整个数组向右平移100000个单位,这样可以避免数组下标为负数的情况
设c=100000,f[j]表示重量为j-c时所能取得的最大价值。若f[j]=-inf表示不能取到j-c的重量。则有方程f[j]=max(f[j],f[j-a[i]]+b[i]),若f[j-a[i]]≠-inf,a[i]表示重量,b[i]表示价值
注意01背包当数组是一维是要倒序循环,但当重量为负值时又要改成正序循环,和倒序循环是一样的道理,避免把同一个物品当做使用了多次
1 #include<iostream> 2 #include<algorithm> 3 using namespace std; 4 const int c=1e5; 5 const int maxn=200002; 6 const int inf=1e9; 7 int f[maxn+10],a[110],b[110]; 8 int n,i,j,k,ans,m,t; 9 10 int main(){ 11 //freopen("poj2184.txt","r",stdin); 12 cin>>n; 13 for (i=1;i<=n;i++) cin>>a[i]>>b[i]; 14 for (i=0;i<=maxn;i++) f[i]=-inf; 15 f[c]=0; //将0点前移100000 16 for (i=1;i<=n;i++){ 17 if (a[i]>=0){ 18 for (j=maxn;j>=a[i];j--) 19 if (f[j-a[i]]!=-inf) f[j]=max(f[j],f[j-a[i]]+b[i]); 20 } 21 else{ 22 for (j=0;j<=maxn+a[i];j++) //若a[i]为负,正向循环 23 if (f[j-a[i]]!=-inf) f[j]=max(f[j],f[j-a[i]]+b[i]); 24 } 25 } 26 ans=0;t=0; 27 for (j=c;j<=maxn;j++){ 28 if (f[j]>=0) ans=max(ans,j-c+f[j]); 29 t=1; 30 } 31 if (t==0) cout<<0<<endl;else cout<<ans<<endl; 32 //fclose(stdin); 33 return 0; 34 }