POJ-2184 Cow Exhibition---01背包变形(负数偏移)

题目链接:

https://vjudge.net/problem/POJ-2184

题目大意:

给出num(num<=100)头奶牛的S和F值(-1000<=S,F<=1000),要求在这几头奶牛中选出若干头,使得在其总S值TS和总F值TF均不为负的前提下,求最大的TS+TF值

思路:

可以把S当体积,F当价值做01背包。但是注意是S可为负,所以整体加100000,然后要注意DP顺序,S为负是要顺序,为正时逆序。

还有就是注意DP时的范围,凡是可能影响的都要包括。

 1 //#include<bits/stdc++.h>
 2 #include<iostream>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn = 105;
 6 const int maxm = 2e5+10;
 7 const int INF = 0x3f3f3f3f;
 8 int v[maxn], w[maxn];
 9 int dp[maxm];
10 int T, n;
11 double m;
12 int main()
13 {
14     int k = 100000;//整体偏移k位,dp[k]就是标准的dp[0]
15     while(cin >> n)
16     {
17         memset(dp, -INF, sizeof(dp));
18         dp[k] = 0;//注意初始化
19         int x, y;
20         for(int i = 0; i < n; i++)
21         {
22             cin >> x >> y;
23             
24             //这里不能写if(x+y<0)continue;这是错误的贪心,一开始因为这个地方一直WA,因为有些x+y<0加入是由于x>0 y<0,x的加入使得x和其他的最优解非负
25             if(x <= 0 && y <= 0)continue;//可以直接由贪心排除
26 
27             if(x < 0)//x小于0,dp转移方向从前往后,因为每一步dp[i]需要dp[i-x]更新,由于是负数i-x>i
28             {
29                 for(int i = 0; i <= 2 * k + x; i++)
30                     if(dp[i - x] > -INF)//这里不能省略,如果dp[i - x]为-INF,那么就不可以更新前面的值
31                         dp[i] = max(dp[i], dp[i - x] + y);
32             }
33 
34             else //x大于0,dp转移方向从后往前,就是01背包
35             {   
36                 for(int i = 2 * k; i >= x; i--)
37                     if(dp[i - x] > -INF)
38                         dp[i] = max(dp[i], dp[i - x] + y);
39             }   
40         }
41         int ans = 0;
42         for(int i = k; i <= 2 * k; i++)//从k开始,结果减去k
43             if(dp[i] >= 0)//此处必须大于0,因为dp[i]为TF的值,题目要求TF非负
44                 ans = max(ans, dp[i] + i - k);
45         cout<<ans<<endl;
46     }
47     return 0;
48 }
原文地址:https://www.cnblogs.com/fzl194/p/8784550.html