"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.
题解:
这个题目真的提交了好多次才A,这个事情告诉我们,写代码不能写得太丑,不然复杂度对的也A不了。
好了,这个题目可以抽象为n个物品,每个物品有两个属性,ai,bi,要求最大化sum(ai+bi),并且ai的合或者bi的合都不能为负数。
那么很显然的dp,dp[i][j]表示dp到i这个物品,ai和为j的最大bi和,那么转移就是取和不取两个即:dp[i][j]=max(dp[i-1][j],dp[i-1][j-a[i]]+b[i])。但为什么会交很多遍呢?有一些细节。
首先要整体平移j,因为有可能为负数。2.初始化要为-inf,防止不合法状态跟新其他状态。3.初始化是dp[0][0]=0,因为当你什么都不选时,最大的b值也是0.
代码:
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <iostream> #define ll long long #define MAXN 101000 #define MAXN2 111000 #define inf 10000000000000 #define RG register using namespace std; ll dp[2][MAXN*3]; int a[200],b[200]; int n,shang=0,xia=0,move=100100; int main() { scanf("%d",&n); for(RG int i=1;i<=n;i++) { scanf("%d%d",&a[i],&b[i]); if(a[i]>0) shang+=a[i]; else xia+=a[i]; } memset(dp,-127,sizeof(dp)); int now=0,last=1; dp[0][move]=0; for(RG int i=1;i<=n;i++){ now^=1,last^=1; for(RG int j=xia;j<=shang;j++){ dp[now][j+move]=max(dp[last][j+move],dp[last][j-a[i]+move]+b[i]); } } ll ans=0; for(RG int i=0;i<=shang-xia;i++){ if(dp[now][i+move]<0) continue; ans=max(ans,i+dp[now][i+move]); } printf("%lld",ans); return 0; }