HDU 1574 RP问题 (dp)

题目链接

Problem Description

在人类社会中,任何个体都具有人品,人品有各种不同的形式,可以从一种形式转换为另一种形式,从一个个体传递给另一个个体,在转换和传递的过程中,人品不会消失,也不被能创造,这就是,人品守恒定律!

人品守恒定律更形象的描述,当发生一件好事,你从中获利,必定消耗一定量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值可能为负。

Input

输入数据的第一行为一个正整数T,表示有T组测试数据。每组测试数据的第一行为一个正整数N (0 < N <= 1000),表示这个时间段在你身上可能发生N个事件。接下来N行,每行有三个整数a, b, c (0 <= |a| <= 10, 0 <= |b| <= 10000, 0 <= |c| <= 10000)。这N个事件是按照输入先后顺序先后发生的。也就是说不可能先发生第i行的事件,然后再发生i – j行的事件。

Output

对应每一组输入,在独立一行中输出一个正整数,表示最大可能获益值。

Sample Input

3
1
-1 0 1
2
10 200 -1
-5 8 3
3
-5 0 4
10 -5 -5
-5 5 10

Sample Output

1
2
9

分析:

这个题目要分析a的正负取值。之后进行运算。。。当a为正数的时候,rp一定是要小于b的。所以从b+10000到0枚举。当a为负数的时候,rp一定是要大于b的。所以从b+10000到最大的那个范围枚举的。。比较的是那个加了那些人品之后和加上获得的人品值的大小。。。要有一个标记。看是不是都存在,如果不存在直接dp的话不合理。因为存在着未知的一些值。最后求一个最大的值就ok啦!~~~~~

代码:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<string.h>
using namespace std;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int N,i,j,a,b,c,max1=-0x3f3f3f3f;
        scanf("%d",&N);
        int dp[20020];
        for(i=0;i<20020;i++)
            dp[i]=-0x3f3f3f3f;
        dp[10000]=0;
        for(i=1; i<=N; i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(a>0)
            {
                for(j=10000+b;j>=0;j--)
                    dp[j+a]=max(dp[j+a],dp[j]+c);
            }
             else
            {
                for(j=10000+b;j<=20000;j++)
                    dp[j+a]=max(dp[j+a],dp[j]+c);
            }
        }
        for(i=0;i<20020 ;i++)
            if(dp[i]>max1)
            max1=dp[i];
        printf("%d
",max1);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/cmmdc/p/6766766.html