RP问题
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 726 Accepted Submission(s): 216
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值可能为负。
人品守恒定律更形象的描述,当发生一件好事,你从中获利,必定消耗一定量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
Author
lwg
Source
Recommend
linle
好久啊~~就是一递推~
#include <iostream>
#include <cstring>
#include <cstdio>
#define inf 0x3f3f3f3f
using namespace std;
int dp[20005];
int vis[20005];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int i,a,b,c;
memset(vis,0,sizeof(vis));
for(i=0;i<=20000;i++)
dp[i]=-inf;
dp[10000]=0;
vis[10000]=1;
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&a,&b,&c);
b+=10000;
int j;
if(a<0)
{
for(j=b;j<=20000;j++)
{
if(vis[j]==1)
{
if(vis[j+a])
dp[j+a]=max(dp[j]+c,dp[j+a]);
else
{
dp[j+a]=dp[j]+c;
vis[j+a]=1;
}
}
}
}
else
{
//printf("asdf %d\n",a+b);
for(j=b;j>=0;j--)
{
if(vis[j]==1)
{
if(vis[j+a]==1)
dp[j+a]=max(dp[j+a],dp[j]+c);
else
{
dp[j+a]=dp[j]+c;
vis[j+a]=1;
}
//printf("%d %d %d \n",c,j-a,dp[j]);
}
}
}
}
int mm=-inf;
for(i=0;i<=20000;i++)
{
if(vis[i]==1&&mm<dp[i])
mm=dp[i];
}
printf("%d\n",mm);
}
return 0;
}
还有一个代码不知道为什么错:求指教
#include <iostream>
#include <cstring>
#include <cstdio>
#define inf 0x3f3f3f3f
using namespace std;
int dp[20005];
int vis[20005];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int i,a,b,c;
memset(vis,0,sizeof(vis));
for(i=0;i<=20000;i++)
dp[i]=-inf;
dp[10000]=0;
vis[10000]=1;
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&a,&b,&c);
b+=10000;
int j;
if(a<0)
{
for(j=a+b;j<=20000;j++)
{
if(vis[j-a]==1)
{
if(vis[j])
dp[j]=max(dp[j-a]+c,dp[j]);
else
{
dp[j]=dp[j-a]+c;
vis[j]=1;
}
}
}
}
else
{
//printf("asdf %d\n",a+b);
for(j=a+b;j>=a;j--)
{
if(vis[j-a]==1)
{
if(vis[j])
dp[j]=max(dp[j-a]+c,dp[j]);
else
{
dp[j]=dp[j-a]+c;
vis[j]=1;
}
//printf("%d %d %d \n",c,j-a,dp[j]);
}
}
}
}
int mm=-inf;
for(i=0;i<=20000;i++)
{
if(vis[i]==1&&mm<dp[i])
mm=dp[i];
}
printf("%d\n",mm);
}
return 0;
}
268

被折叠的 条评论
为什么被折叠?



