hit dp

dp

魔法少女Clara非常仰慕又可爱又是BZOJ的Rank1又可爱有WorldFinalRank20又可爱又Regional出题人又可爱又能n2过百万又可爱的魔法扶扶Claris,所以希望能够通过训练变得像魔法扶扶Claris一样强。由于魔法少女Clara非常懒,所以她找到姚主席寻求帮助。姚主席在接下来的n天中,每天都准备了一套题目用于训练,第i天的题目难度为Ci。魔法少女Clara希望在其中选择至多m天陪姚主席训练(因为其他的时间,她要用来收集退环境的骷髅牌,炸鱼,和无头学姐立下flag,摔跤健身,释放多元重奏饱和炮击,练习膜法并传授膜法给下一代魔法少女们,以及和其他世界线的自己补魔)。假设魔法少女Clara当前的实力值为x,若她做一套难度为y的题目,则:

    当y<x-100时,魔法少女Clara通过炸鱼获得了精神上的愉悦, 实力值变为0;

    当x-100<=y<=x时,魔法少女Clara锻炼了手速, 实力值增加1;

    当x<y<=x+100时,魔法少女Clara获得了充分的锻炼, 实力值增加(y-x+1)/2(向下取整);

    当y>x+100时,魔法少女Clara成功或者失败的挑战了自己的极限, 实力值增加5000/(y-x)(向下取整)。

    魔法扶扶Claris听说了魔法少女Clara的计划之后,非常感动,所以决定给魔法少女Clara一次机会,让她接受魔法扶扶Claris的亲♂身♂指♂导。具体来说,魔法少女Clara可以选择这n天中的连续3天用于接受特殊训练:若魔法少女Clara在特殊训练前的实力值不超过2148473547,则特殊训练会使得她的实力值增加100;否则,会使她的实力值增加99。值得注意的是,这3天占用的是m天训练的时间,也就是说,如果魔法少女Clara选择了某连续的3天接受特殊训练,则只剩下m-3天可以陪姚主席训练了。

    魔法少女Clara初始实力值为0。她的非常想变强,所以希望你来帮她指定一个计划,在这n天中选择至多m天用来陪姚主席训练和接受魔法扶扶Claris的特殊训练,使得这n天结束之后,魔法少女Clara最终的实力值尽可能高。你只需要告诉他这个尽可能高的实力值是多少即可。

Input

    输入数据的第一行为一个整数T(1 <= T <= 10),表示数据组数。接下来T组数据:

    每组数据的第一行是两个整数n和m(1 <= m <= n <= 3000),
    表示总的天数和魔法少女Clara可以用来训练的天数;

    第二行有n个整数,第i个整数Ci表示姚主席第i天训练的题目的难度(0 <= Ci <= 1e8)。

Output
对于每组数据,在单独的一行中输出"Case #K: ANS",其中整数K表示当前是第K组数据,整数ANS表示n天后魔法少女Clara所能达到的最高的实力值。

Sample Input
3
3 3
100 100 100
3 3
100 150 200
7 6
0 0 0 200 0 0 0

Sample Output
Case #1: 100
Case #2: 150
Case #3: 150

Hint

    对于第一组数据,若魔法少女Clara接受特殊训练,则实力值为100;否则,魔法少女Clara和姚主席训练3天,第一天结束后实力值为50,第二天结束后实力值为75,第三天结束后实力值为88,故答案为100;

    对于第二组数据,若魔法少女Clara接受特殊训练,则实力值为100;否则,魔法少女Clara和姚主席训练3天,第一天结束后实力值为50,第二天结束后实力值为100,第三天结束后实力值为150,故答案为150;

    对于第三组数据,魔法少女Clara前三天接受特殊训练,第四天陪姚主席训练,剩下三天不训练,最终答案为150。
#include<bits/stdc++.h>
using namespace std;
int f[3009][3009][2];//f[i][j][0/1]表示前j节课选i节,k=0表示用过了3天的机会,1相反。
int shu[3009];
int main()
{
    
    
//	freopen("data.in","r",stdin);
//	freopen("my.out","w",stdout);
	int t,n,m;
	scanf("%d",&t);
	int t1=1;
	while(t1<=t)
	{
    
    
		printf("Case #%d: ",t1);
		++t1;
		int ans=-1;
		memset(f,0,sizeof(f));
		scanf("%d%d",&n,&m);
		for(int i=1;i<=n;i++)
			scanf("%d",&shu[i]);
		for(int i=0;i<=m;i++)
		for(int j=0;j<=n;j++)
		for(int k=0;k<=1;k++)
		{
    
    
			if(k==0)
			{
    
    
				if(shu[j+1]>=f[i][j][k]-100&&shu[j+1]<f[i][j][k])
					f[i+1][j+1][k]=max(f[i][j][k]+1,f[i+1][j+1][k]);
				if(shu[j+1]>=f[i][j][k]&&shu[j+1]<=f[i][j][k]+100)
					f[i+1][j+1][k]=max(f[i+1][j+1][k],f[i][j][k]+(shu[j+1]-f[i][j][k]+1)/2);
				if(shu[j+1]>f[i][j][k]+100)
					f[i+1][j+1][k]=max(f[i+1][j+1][k],f[i][j][k]+5000/(shu[j+1]-f[i][j][k]));
				
			}
			if(k==1)
			{
    
    
				if(shu[j+1]>=f[i][j][k]-100&&shu[j+1]<f[i][j][k])
					f[i+1][j+1][k]=max(f[i][j][k]+1,f[i+1][j+1][k]);
				if(shu[j+1]>=f[i][j][k]&&shu[j+1]<=f[i][j][k]+100)
					f[i+1][j+1][k]=max(f[i+1][j+1][k],f[i][j][k]+(shu[j+1]-f[i][j][k]+1)/2);
				if(shu[j+1]>f[i][j][k]+100)
					f[i+1][j+1][k]=max(f[i+1][j+1][k],f[i][j][k]+5000/(shu[j+1]-f[i][j][k]));
				f[i+3][j+3][k-1]=max(f[i][j][k]+100,f[i+3][j+3][k-1]);
			}
			f[i][j+1][k]=max(f[i][j][k],f[i][j+1][k]);//不选
			ans=max(ans,f[i][j][k]);
		}
		printf("%d\n",ans);
//		printf("%d\n",max(f[m][n][0],f[m][n][1]));
	}
	return 0;
}

有一点强调的就是要考虑不想选当前课程的状态的继承。

猜你喜欢

转载自blog.csdn.net/m0_50089378/article/details/109276650
今日推荐