题目:(https://www.luogu.com.cn/problem/P2340)
01背包
奶牛想证明它们是聪明而风趣的。为此,贝西筹备了一个奶牛博览会,她已经对 N 头奶牛进行了面试,确定了每头奶牛的智商和情商
贝西有权选择让哪些奶牛参加展览。由于负的智商或情商会造成负面效果,所以贝西不希望出展奶牛的智商之和小于零,或情商之和小于零。满足这两个条件下,她希望出展奶牛的智商与情商之和越大越好,请帮助贝西求出这个最大值
//洛门永存
const int N = 400010;
int dp[N * 2];
void solve(){
int n; cin >> n;
vector<int> iq(n + 1), eq(n + 1);
for (int i = 1; i <= n; i ++ ) cin >> iq[i] >> eq[i];
memset(dp, -0x3f, sizeof dp);
dp[400000] = 0;
for (int i = 1; i <= n; i ++ ){
//确定每一个牛可以影响的所有状态,其中包括不符合条件和符合条件的情况
if (iq[i] >= 0){//当这个b的智商高于0时的状态转移
for (int j = 800000; j >= iq[i]; j -- )
dp[j] = max(dp[j], dp[j - iq[i]] + eq[i]);
}
else{//这个b的智商低于0时的状态转移
for (int j = 0; j <= 800000 + iq[i]; j ++ )
dp[j] = max(dp[j], dp[j - iq[i]] + eq[i]);
}
}
int ans = 0;
for (int i = 400000; i <= 800000; i ++ ){
if (dp[i] >= 0)//同时限定两个条件,智商和情商都大于0时
ans = max(ans, i + dp[i] - 400000);
}
cout << ans << endl;
}
input:
5
-5 7
8 -6
6 -3
2 1
-8 -5
output:
8
在数组下标可能为负数时,将其右移可以有效避免数组越界。但是在最后求答案时,不要忘记我们求得其实是 dp[j]+j−400000的最大值.你要是真打开了这个题的题解,你可以发现这确实是某个题解的原话(bushi).
此外这道题还有一个教训吧…
一开始我是想使用状态机模型去想的但是没有搓出相关的状态转移方程式,而且dp数组的值设置的是PII类型,然后发现就寄了.所以这道题开拓了思路,可以把类似本题智商这个值的值放到状态里面,从而将题目转化为背包,减少一个值,这样根据此种状态可以容易写出状态转移方程.
然后代码不是我写的,太菜了,只不过题确实是好题,绿题薄纱我