POJ 2184 Cow Exhibition 01背包

来源:互联网 发布:猪湾事件知乎 编辑:程序博客网 时间:2024/06/16 05:53

题目链接

题目大意就是给每个牛的Si和Fi,要你选出一些牛使他们的Si和Fi的总和最大,并且他们的Si的总和不为0,Fi也是一样。

一开始看确实不好想,后来看了别人才知道,把Si看成花费,Fi看成价值。
不就是我们熟悉的01背包了吗。

但是,问题来了,题目里有负数,所以这题难点就在这里,你需要想一个办法解决。

看看数据范围。发现最大-10w,最大+10w
扩大数组,设置基准为10w , 这样子 0 就代表-10w ,20w就代表10w
设置dp[100000] = 100000;
这样子就可以通过dp[x] 是否等于0来判断是否合法

但是如果Fi是负数,就得从小开始搜。

而且20w的数据范围,容易超时,所以一开始用l和r来识别所要用到的区间

下面贴代码

#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <queue>using namespace std;int dp[200005];int mid = 100002;int n;int main(){    dp[mid] = mid;    int c,w;    scanf("%d",&n);    int l = mid,r = mid;    for(int i=0;i<n;i++){        scanf("%d%d",&c,&w);        l = min(l,l+c);        r = max(r,r+c);        if(c>0){            for(int j=r;j>=l;j--){                if(dp[j-c])                dp[j] = max(dp[j],dp[j-c]+w);            }        }else {            for(int j=l;j<=r;j++){                if(dp[j-c])                dp[j] = max(dp[j],dp[j-c]+w);            }        }    }    int res = 0;    for(int i=mid;i<=200005;i++){        if(dp[i]>=mid) res = max(res,dp[i]+i-mid-mid);    }    printf("%d\n",res);    return 0;}
0 0
原创粉丝点击