HDU - 1574 RP问题(01背包)

题目大意:在人类社会中,任何个体都具有人品,人品有各种不同的形式,可以从一种形式转换为另一种形式,从一个个体传递给另一个个体,在转换和传递的过程中,人品不会消失,也不被能创造,这就是,人品守恒定律!
人品守恒定律更形象的描述,当发生一件好事,你从中获利,必定消耗一定量RP;当发生一件不幸的事,你在其中有所损失,必定积攒一定量RP。
假设在一个时间段内在你身上可能会发生N个事件,每个事件都对应一个RP变化值a、RP门槛值b和获益值c。当RP变化值a为正,获益值c必定为负,只有你当前的RP值小于等于RP门槛值b的时候,此事件才有可能发生,当此事件发生时,你的RP值将增加|a|,获益值将减少|c|。反之,当RP变化值a为负,获益值c必定为正,只有你当前的RP值大于等于RP门槛值b的时候,此事件才有可能发生,当此事件发生时,你的RP值将减少|a|,获益值将增加|c|。
一个事件在满足上述RP条件的前提下,未必会发生。假设在这段时间之前你所具有的RP值和获益值都为0,那么过了这段时间后,你可能达到的最大获益值是多少?
注意:一个人的所具有的RP值可能为负。

解题思路:01背包,分类讨论一下就可以
因为RP只能在[-10000,10000],且有可能为负数,所以就每个RP值加上10000,这样就不会出现负的情况了

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 20010;
const int INF = 0x3f3f3f3f;
int dp[N];
bool vis[N];
int n;

void solve() {
    memset(dp, 0, sizeof(dp));
    memset(vis, 0, sizeof(vis));
    vis[10000] = true;
    dp[10000] = 0;

    int a, b, c;
    scanf("%d", &n);

    for (int i = 0; i < n; i++) {
        scanf("%d%d%d", &a, &b, &c);
        if (a > 0) {
            for (int j = b + 10000; j >= 0; j--) {
                if (vis[j]) {
                    if (!vis[j + a]) {
                        dp[j + a] = dp[j] + c;
                        vis[j + a] = true;
                    }
                    else dp[j + a] = max(dp[j + a], dp[j] + c);
                }
            }

        }
        else if (a < 0) {
            for (int j = b + 10000; j < 20010; j++) {
                if (vis[j]) {
                    if (!vis[j + a]) {
                        vis[j + a] = true;
                        dp[j + a] = dp[j] + c;
                    }
                    else dp[j + a] = max(dp[j + a], dp[j] + c);
                }
            }
        }
    }
    int ans = -INF;
    for (int i = 0; i < 20010; i++) 
        ans = max(dp[i], ans);

    printf("%d\n", ans);
}

int main() {
    int test;
    scanf("%d", &test);
    while (test--) {
        solve();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值