poj 2184--Cow Exhibition

13 篇文章 0 订阅
本文探讨了一种01背包问题的变形,即在存在负数元素的情况下,如何寻找使得s和f总和最大的子集。通过将区间平移至0~200000,并利用动态规划实现,文章详细解释了如何根据不同元素的正负性调整遍历顺序,最终从新的原点出发计算最大总和。
摘要由CSDN通过智能技术生成

有一群奶牛,每一头都有s[i], f[i]两个值。在其中找一个子集,要在保证这两个值均为非负的情况下,使s和f的总和最大。

http://poj.org/problem?id=2184


这是01背包的变形,因为有负值的存在,背包的体积为-100000~100000

我们可以将区间平移到0~200000,原点就变成了100000

在进行01背包时,dp[v] = max(dp[v], dp[v - c[i]] + w[i],要用dp[v - c[i]]更新dp[v],所以要从大到小遍历。

但当c[i] < 0时,要从小到大遍历,因为v - c[i] > v。


在遍历结果的时候要从新的原点100000开始

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf = 0x3f3f3f3f;
int n, s[1000 + 10], f[1000 + 10], dp[200000 + 10];
int main(){
    scanf("%d", &n);
    for(int i=0; i<n; i++){
        scanf("%d%d", &s[i], &f[i]);
    }
    for(int i=0; i<=200000; i++) dp[i] = -inf;
    dp[100000] = 0;
    for(int i=0; i<n; i++){
        if(s[i] > 0){
            for(int j=200000; j>=s[i]; j--) dp[j] = max(dp[j], dp[j - s[i]] + f[i]);
        }
        else{
            for(int j=0; j<=200000+s[i]; j++) dp[j] = max(dp[j], dp[j - s[i]] + f[i]);
        }
    }
    int ans = 0;
    for(int i=100000; i<=200000; i++){
        if(dp[i] > 0) ans = max(dp[i] + i - 100000, ans);
    }
    printf("%d\n", ans);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值