Cow Exhibition [POJ2184] [DP] [背包的负数处理]

题意:

有很多羊,每只羊有一个幽默度和智商,要选出一些羊,智商加幽默度总和最大,其中智商总和和幽默度总和都不能是负数。

样例输入:
5
-5 7
8 -6
6 -3
2 1
-8 -5
样例输出:
8
分析:
这很像一个01背包题,但是有两个价值,却没有重量
我们就把其中一个看成重量,另一个看成价值
答案就是max(i+dp[i])
那如何保证数据大于0呢?
我们可以把价值总体向右移100000个单位,然后设原点O为100000
之后就可以进行dp了
转移方程仍是:dp[j]=dp[j-w[i]]+v[i];
但要注意,如果w[i]>=0要逆向循环,w[i]<0要顺向循环,确保是01背包而不是完全背包
最后计算结果时,从O向右枚举,保证了重量不为负数,dp[i]>=0,保证价值不为负数
再从中选max(i-O+dp[i])
代码:
 1 #include<set>
 2 #include<map>
 3 #include<queue>
 4 #include<stack>
 5 #include<cmath>
 6 #include<cstdio>
 7 #include<cstring>
 8 #include<iostream>
 9 #include<algorithm>
10 #define RG register int
11 #define rep(i,a,b)    for(RG i=a;i<=b;++i)
12 #define per(i,a,b)    for(RG i=a;i>=b;--i)
13 #define ll long long
14 #define inf (1<<29)
15 #define O 100000
16 #define maxn 105
17 #define maxm 200005
18 using namespace std;
19 int n;
20 int dp[maxm],v[maxn],w[maxn];
21 inline int read()
22 {
23     int x=0,f=1;char c=getchar();
24     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
25     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
26     return x*f;
27 }
28 int main()
29 {
30     n=read();
31     rep(i,1,n)    w[i]=read(),v[i]=read();
32     //memset(dp,-63,sizeof(dp));
33     dp[O]=0;
34     rep(i,1,n)
35     {
36         if(v[i]>=0)
37             per(j,maxm-1,v[i])
38                 dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
39         else
40             rep(j,0,maxm-1+v[i])
41                 dp[j]=max(dp[j],dp[j-v[i]]+w[i]);
42     }
43     int ans=0;
44     rep(i,O,maxm-1)
45         if(dp[i]>=0)
46             ans=max(ans,dp[i]+i-O);
47     cout<<ans;
48     return 0;
49 }
View Code

猜你喜欢

转载自www.cnblogs.com/ibilllee/p/9219019.html