POJ 2184 Cow Exhibition (01背包)

题目大意:N个有两个属性Si、Fi的物品,从中选出几个使得sigma(Si) + sigma(Fi)最大,并且两者都必须是非负数.   比较好的一道题,考查对01背包的理解和运用能力. 对于这种一个物品两个属性的问题,即使没有什么体积或者价值那么明显的情况,我们也应该考虑一下01背包是否可行.其实01背包不在于解决什么体积、价值问题,而在于这种动态规划的方法可以记录下来选择某些物品时,得到一个属性的值所对应的时刻另一个属性最优的状态.(这仅是我的拙见……) 那么显然我们就可以通过01背包来得到不同Si的值所对应能得到的Fi的最优值,然后通过枚举所有可能得到的Si值即可比较出最优解. 注意一点就是因为si[i]可能为负,所以范围要扩大一倍. 另外还需要注意对01背包第二层枚举顺序的理解:当si[i]>0时我们从大到小搜,当si[i]<0时从小到大搜.(理解不了的去看《背包九讲》吧~~)   (。。尼玛这题TLE+RE n次。。最后一看。。我们范围100000算成1000000了= =。。。捉鸡。。。  
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define MID(x,y) ((x+y)>>1)
using namespace std;
typedef long long LL;
int f[201010];
int si[110],fi[110];
int main(){
    int n;
    int inf = - (1 << 30);
    scanf("%d", &n);
    for (int i = 0; i < n; i ++)
        scanf("%d%d", &si[i], &fi[i]);
    for (int i = 0; i < 201010; i ++)
        f[i] = inf;
    f[100000] = 0;
    for (int i = 0; i < n; i ++)
        if (si[i] < 0 && fi[i] < 0)
            continue;
        else if (si[i] > 0)
            for (int j = 200000; j >= si[i]; j --)
                if (f[j - si[i]] > inf)
                    f[j] = max(f[j], f[j - si[i]] + fi[i]);
                else;
        else
            for (int j = si[i]; j <= 200000+si[i]; j ++)
                if (f[j - si[i]] > inf)
                    f[j] = max(f[j], f[j - si[i]] + fi[i]);
    int ans = 0;
    for (int i = 100000; i <= 200000; i ++)
        if (f[i] >= 0 && i - 100000 + f[i] > ans)
            ans = i - 100000 + f[i];
    printf("%d\n", ans);
	return 0;
}
 
举杯独醉,饮罢飞雪,茫然又一年岁。 ------AbandonZHANG
原文地址:https://www.cnblogs.com/AbandonZHANG/p/4113999.html