1750. 运动会
Constraints
Time Limit: 1 secs, Memory Limit: 32 MB
Description
ZEH是一名04级的学生,他除了绩点高,还有运动细胞。有一次学院举办运动会,ZEH发现里面的项目都是他所向披靡的,当然他想获得所有项目的No1,但是一个人的精力总是有限的,ZEH也是只有P(Power的简写,一个大于0且小于1000的整数)的精力。如果精力足够参加比赛,一定能赢;相反,精力不够去参加比赛,Loss的概率很大,ZEH当然不想因为Loss而不爽。
整个运动会有N(大于0且小于等于100)项比赛,每项比赛都是在指定的一天D(D大于等于0)内举行完,但是一天可能同时有多个比赛同时进行,ZEH当然就不能同时兼顾。比赛结束后,院长都会亲自为冠军颁发一定数额的奖金,其他名次只有一张奖状。ZEH当然是冲着奖金去的,他想获得最多的奖金,师弟师妹们,你能帮ZEH大牛计算出他最多能拿多少奖金吗?
Input
第一行是一个整数T,表示这题有T个用例。
每个用例的第一行有两个正整数P N,分别表示ZEH的精力和比赛的项目。
第二行到第N+1行是N个项目,每一行有三个正整数D E M,分别表示这个项目在第D天举行,需要E的精力,和比赛的奖金。项目的顺序都按D排好序。
Output
对于每个用例,输出他能拿的最多的奖金。
Sample Input
1 14 5 0 3 7 0 2 5 1 4 2 2 6 14 2 8 15
Sample Output
23
经典分组背包问题,利用状态转移方程直接可以写成核心代码。关于分组背包问题:
本题需要注意几个问题,1、输入的第D天,这些D值不一定是连续的,2、输入的E,即需要消耗的能量,可能是0。
#include <iostream>
#include <algorithm>
using namespace std;
int main()
{
int t;
int f[1000],d[100],w[100],v[100];
cin>>t;
while(t--)
{
int p,n,index=0;
int day[100]={0};
memset(f,0,sizeof(f));
memset(d,0,sizeof(d));
cin>>p>>n;
for(int i=0; i<n; i++)
{
cin>>d[i]>>w[i]>>v[i];
}
day[0] = 1;//根据天数分组,统计好每天的比赛个数
for(int i=1; i<n; i++)
{
if(d[i] != d[i-1])
index++;
day[index]++;
}
int count = 0;
for(int i=0; i<=index; i++)
{
count = count + day[i];
for(int j=p; j>=0; j--)
{
int curr = f[j];
for(int k=0; k<day[i]; k++)
{
int tmp = count - day[i] + k ; //一维数组存放的,需要找到第i 天第k 项所对应的index。
if( j>= w[tmp] && curr < f[j-w[tmp]]+v[tmp])
curr = f[j-w[tmp]]+v[tmp];
}
f[j] = curr;
}
}
cout<<f[p]<<endl;
}
//system("pause");
return 0;
}