poj2184 cow exhibition

题目链接: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 }
poj2184

 

posted @ 2020-04-27 00:17  coastal_taipan  阅读(186)  评论(0编辑  收藏  举报