T4 分配时间 题解

问题描述
小王参加的考试是几门科目的试卷放在一起考,一共给 t 分钟来做。他现在已经知道每
门科目花的时间和得到的分数的关系,还有写名字要的时间(他写自己的名字很慢)请帮他
算一下他最高能得几分。总分一定时,第一门科目成绩尽量高,第一门科目成绩也一样时,
第二门科目成绩尽量高……以次类推。如果放弃某一门的考试(花的时间为 0),那么
名字也就不用写了。
 
输入格式
第一行三个正整数 t,n,name. t 是总时间,n 表示考 n 个科目,name 表示写名字要的
时间(每一门科目写名字时间一样)。接下来 n 行,每行 t 个正整数,第 i 个数表示时间为
i 时这门科目的分数(不一定递增)。时间为 0 时这门科目的分数为 0,所以就不读入了。
 
输出格式
一个数,即总分。
 
样例输入
5 3 1
1 2 3 4 5
2 3 3 4 6
3 3 3 2 5
样例输出 
 4 / 4 内部资料,版权所有
6
样例说明 
第一门:0 分钟;第二门:3 分钟,写名字 1 分钟,做题目 2 分钟,得 3 分;第三门:2
分钟,写名字 1 分钟,做题目 1 分钟,得 3 分。总共得 6 分。
数据范围
对于 50 %的数据,n<=4
对于 100 %的数据,n<=10,t<=100, 所有数据都在 longint 范围内

这个题看起来蛮正经的,一种浓浓的背包气息散发出来。我们就直接按照01背包做就好了,每科可以选择做多长时间,然后一个dp数组,dp[i][j]表示查看前i科,花费j点时间,最多可以得多少分。顺推就好了(虽然感觉很难想的样子,但就是讲不出来……尽量讲清楚一点)。

下面就是代码了:

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
long long n,t,name,e,shu;
long long sz[25][200];//开这么大有很多好处,首先不会re,我看着也顺眼
long long dp[25][200];
int main()
{
	freopen("times.in","r",stdin);
	freopen("times.out","w",stdout);//freopen
	scanf("%lld%lld%lld",&t,&n,&name);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=t;j++)
		{
			scanf("%lld",&sz[i][j]);//读入
		}
	}
	for(int i=0;i<=n;i++)
	{
		for(int j=0;j<=t;j++)//前2层循环是遍历科目和总时间的
		{
			for(int k=0;k<=t;k++)//k是准备在第i+1科考试做多长时间。
			{
				e=name+k+j;//已经用了j分钟,这一科做k分钟,写名字name分钟。
				if(k==0)//这一科不做,就不用写名字
				{
					e-=name;
				}
				if(e>t)//时间不够了
				{
					break;
				}//dp[i+1][e]是说,前i+1科,共用e分钟,得到的最大分数。
				dp[i+1][e]=max(dp[i+1][e],dp[i][j]+sz[i+1][k]);//原来和这次的对比。
			}
			if(i==n)
			{
				shu=max(dp[i][j],shu);//不一定是递增的,所以j是几都要判断
			}
		}
	}
	cout<<shu<<endl;
	return 0;
}

这玩意真难讲,明明可以很正当的想到,但讲不出来,如果大家觉得听不懂,可以看看别的大佬的博客。

posted @ 2020-05-18 09:44  lichangjian  阅读(375)  评论(0编辑  收藏  举报