HDU:RP问题

RP问题

Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1038    Accepted Submission(s): 386


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
#include<iostream>
#include<stdio.h>
#include<cstring>
#include<algorithm>
#define max(a,b)a>b?a:b
#define INF -0x3f3f3f3f
using namespace std;
int rp[50000];     //下标代表人品值,数组中存放的是收益值
int main()
{
   int T,N,i,a,b,c;
   scanf("%d",&T);   //T组测试数据
   while(T--)
   {
       int l=10000,r=10000,mmax,temp; //l为下届,r为上届,最初为0+10000,10000的来源是,a最多为-10,测试数据最多有数据最多有1000//个,乘上10的个数,就是10000,也就是说所有a值的和都不会超过-10000,所以权值加上了10000.
       scanf("%d",&N);
       for(i=0;i<=50000;i++)
        rp[i]=INF;     //将数组初始化为负无穷
       mmax=0;      //若所有的数据a都大于0,那我什么都不做,收益值最大只能是0,做任何一件事都会使收益变成负数。
       rp[10000]=0;   //最初人品值和收益值都是0,人品值加权值得10000,那么在rp[10000]初始化收益值为0
       while(N--)
       {
           scanf("%d%d%d",&a,&b,&c); //做这件事人品变化量,门槛值,收益变化量
           b=b+10000;  //b是人品门槛值,加上权值10000
           if(a>0)  //rp<=b;有可能发生,有可能不发生
           {
               for(i=b;i>=l;i--)   //这里从b到l循环的原因是,此时a>0,rp[i+a]都在rp[i]的右边,从b->l避免重复加
               {
                   if(rp[i]!=INF)  
                   {
                     rp[i+a]=max(rp[i]+c,rp[i+a]);  //求发生与不发生谁的收益大
                   }
               }
               r=r+a;  //上届往右移动a
           }
           else if(a<0)  //rp>=b
           {
               for(i=b;i<=r;i++)  //这里循环从b-r的原因是,a<0,rp[i+a]都是rp[i]左边的数,这样走是避免加的值重复
               {
                   if(rp[i]!=INF)
                   {
                       rp[i+a]=max(rp[i]+c,rp[i+a]);
                   }
               }
               l=l+a;  //下界往左移动
           }
    }
    for(i=l;i<=r;i++)  //从下界到上届,找最大值。
        if(rp[i]!=INF&&rp[i]>mmax)
            mmax=rp[i];
    printf("%d\n",mmax);
   }
   return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值