"Fat and docile, big and dumb, they look so stupid, they aren‘t much
fun..."
- Cows with Guns by Dana Lyons
The cows want to prove to the public that they are both smart and fun. In order to do this, Bessie has organized an exhibition that will be put on by the cows. She has given each of the N (1 <= N <= 100) cows a thorough interview and determined two values for each cow: the smartness Si (-1000 <= Si <= 1000) of the cow and the funness Fi (-1000 <= Fi <= 1000) of the cow.
Bessie must choose which cows she wants to bring to her exhibition. She believes that the total smartness TS of the group is the sum of the Si‘s and, likewise, the total funness TF of the group is the sum of the Fi‘s. Bessie wants to maximize the sum of TS and TF, but she also wants both of these values to be non-negative (since she must also show that the cows are well-rounded; a negative TS or TF would ruin this). Help Bessie maximize the sum of TS and TF without letting either of these values become negative.
Input
* Line 1: A single integer N, the number of cows
* Lines 2..N+1: Two space-separated integers Si and Fi, respectively the smartness and funness for each cow.
Output
* Line 1: One integer: the optimal sum of TS and TF such that both TS and TF are non-negative. If no subset of the cows has non-negative TS and non- negative TF, print 0.
Sample Input
5 -5 7 8 -6 6 -3 2 1 -8 -5
Sample Output
8
Hint
OUTPUT DETAILS:
Bessie chooses cows 1, 3, and 4, giving values of TS = -5+6+2 = 3 and TF
= 7-3+1 = 5, so 3+5 = 8. Note that adding cow 2 would improve the value
of TS+TF to 10, but the new value of TF would be negative, so it is not
allowed.
本题难点一:智商与情商是每头奶牛的两种属性,就和东西的重量和价值一样,属于0-1背包问题。
本题难点二:智商情商可以是负数,但是数组下标不允许是负数,所以得加上bias,而这个bias就是总智商的最小值的绝对值即100头牛智商全为最小-1000,也就是bias = 100000,所以范围是0-200000(因为最大是100000,再加上bias就是)。但是情商可以不用加bias,因为dp的值可以是负数。
本题难点三:在一维dp数组情况下原来情商大于等于0是j从大到小遍历的,因为这样可以保证dp[i - 1][j - s[i]]的对应一位dp数组dp[j - s[i]]在dp[j]之后再修改,否则之前修改的话dp[j - s[i]]的值就对应dp[i][j - s[i]]而不是dp[i - 1][j - s[i]]的值,但是如果f[i]小于0,那么dp[i - 1][j - s[i]]就要在dp[i - 1][j]的右边也就是j - s[i] > j,因此如果还是j从大到小就会造成dp[i - 1][j - s[i]]的对应的值dp[j - s[i]]实际上对应dp[i][j - s[i]]的值,因为j - s[i] > j,所以j从大到小的话在dp[j]之前就已经修改好了dp[j - s[i]]的值,就会造成错误,所以此时应当从小到大遍历。综上所述当s[i] >= 0,从大到小,s[i] < 0,从小到大遍历j。
AC代码:
#include <stdio.h> #include <algorithm> using namespace std; const int INF = 0x3fffffff; int s[105], f[105];//s智商,f情商 int dp[200005];//从前i头奶牛中选取奶牛使得的智商为i - bias时,情商的最大值 int ans; int main(void) { int n; scanf("%d", &n); for(int i = 0; i < n; i++) { scanf("%d %d", &s[i], &f[i]); } fill(dp, dp + 200005, -INF);//初始化为不可达 dp[100000] = 0;//实际上对应前0种,也就是初始状态下,智商,情商均为0,因为智商为0时加上bias就是100000 for(int i = 0; i < n; i++) { if(s[i] < 0) { for(int j = 0; j - s[i] <= 200000; j++) if(dp[j - s[i]] != -INF) dp[j] = max(dp[j], dp[j - s[i]] + f[i]); } else { for(int j = 200000; j >= s[i]; j--) if(dp[j - s[i]] != -INF) dp[j] = max(dp[j], dp[j - s[i]] + f[i]); } } for(int i = 100000; i <= 200000; i++)//从智商为0开始遍历,也就是数组下标为bias开始 { if(dp[i] >= 0)//如果智商可达到i且情商大于等于0 ans = max(ans, dp[i] + i - 100000); } printf("%d\n", ans); return 0; }
原文地址:https://www.cnblogs.com/jacobfun/p/12240430.html