[DP] Cow Exhibition POJ - 2184 经典好题
poj.org/problem?id=2184
奶牛想证明他们是聪明而风趣的。为此,贝西筹备了一个奶牛博览会,她已经对N头奶 牛进行了面试,确定了每头奶牛的智商和情商。 贝西有权选择让哪些奶牛参加展览。由于负的智商或情商会造成负面效果,所以贝西不 希望出展奶牛的智商之和小于零,或情商之和小于零。满足这两个条件下,她希望出展奶牛 的智商与情商之和越大越好,请帮助贝西求出这个最大值
Input
第一行:一个整数N,表示奶牛的数量, 1 ≤ N ≤ 100 第二行到第N + 1行:第i + 1行有两个用空格分开的整数: Si和Fi,分别表示第i头奶牛的智商和情商, -1000 ≤ Si ≤ 1000, -1000 ≤ Fi ≤ 1000
Output
第一行:单个整数,表示情商与智商和的最大值。贝西可以不让任何奶牛参加展览,如果这样应该输出 0
这题算是我更深入学习DP的一个开端吧 orz
https://blog.csdn.net/keysona/article/details/45751903 思路是从这篇博客看来的
因为只有选取和不选取的2个状态 所以dfs 爆tmd搜 大概率应该是tle了
不过只有2状态这也提示了 01背包
首先是可以用IQ或EQ作为背包容量 同时加上 100*1000 使之全部为正
然后 以100*1000 为正负分界点 开始类似于01背包的 DP 但是这里不同的是 正负的处理
还有我们通常01背包都是for j=MAXV->weight[i] 从后向前更新
不过这道题 就选择将初始化 -INF 认为-INF为未被物品覆盖的点 将100*1000 认为是零点
这样 凡减去背包容量到 0点或不是-INF的点 将他的val 更新选取最大的
另外 这道题非常重要的 便是更新 正数的时候for j=MAXV->weight[i]
因为正数时 减去这weight 状态是之前来的 如果从 weight[i]->MAXV 就会导致 变成完全背包
负数时 从0开始 因为它的状态是从较大的数来的 因为weight是负的
如果从 MAXV+weight[i] 开始 就又会变成上面所说的完全背包
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <list>
using namespace std;
typedef long long ll;
const int maxn = 105;
const int maxv = 100*1000*2+5;
const int mod = 1e9+7;
const int INF = 0x3f3f3f3f;
const double PI=acos(-1.0);
int IQ[maxn],EQ[maxn];
int dp[maxv];
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>IQ[i]>>EQ[i];
memset(dp,-INF,sizeof(dp));
dp[100*1000]=0;
for(int i=0;i<n;i++){
if(IQ[i]>=0){
for(int j=maxv-5;j>=IQ[i];j--)
if(dp[j-IQ[i]]>-INF) dp[j]=max(dp[j],dp[j-IQ[i]]+EQ[i]);
}
else{
for(int j=0;j<=maxv+IQ[i]-5;j++)
if(dp[j-IQ[i]]>-INF) dp[j]=max(dp[j],dp[j-IQ[i]]+EQ[i]);
}
}
int ans=0;
for(int i=100*1000;i<=maxv-5;i++){
if(dp[i]>0) ans=max(ans,i-100*1000+dp[i]);
}
cout<<ans<<endl;
return 0;
}
最后 for 找 EQ+IQ 最大数据
做完这题收获蛮大的 数据处理 和负数这些状态