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 }
越努力,越幸运