ヒットdp

dp

魔法の少女クララはとても尊敬しています。キュートでBZOJのRank1、キュートでWorldFinalRank20、キュートでリージョナル、キュートで100万を超えるn2が可能で、キュートなマジックがクラリスをサポートしているので、トレーニングを通じてマジックサポートのようになりたいです。クラリスも同様に強いです。魔法の少女クララはとても怠け者なので、八尾会長に助けを求めた。次のn日間、八尾会長は毎日訓練のための一連の質問を用意し、i日目の質問の難易度はCiでした。魔法の少女クララは、八尾会長の訓練に同行するのに最大でm日を選択することを望んでいます(他の時間には、環境から撤退するための頭蓋骨カードを収集し、魚を炒め、頭のない先輩と旗を立て、フィットネスに取り組み、複数のアンサンブル飽和を解放するために使用します砲撃し、映画の方法を練習し、映画の方法を次世代の魔法の女の子、および他の世界的な自己充填魔法に教えます)。魔法の少女クララの現在の強さが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最终的实力值尽可能高。你只需要告诉他这个尽可能高的实力值是多少即可。

入力

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

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

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

出力
データのセットごとに、「ケース#K:ANS」を別の行に出力します。ここで、整数Kは、現在K番目のデータグループであることを示し、整数ANSは、魔法の少女クララがn日間で達成できる最高の強度値を示します。

サンプル入力
3
3 3
100 100 100
3 3
100 150 200
7 6
0 0 0 200 0 0 0

サンプル出力
ケース#1:100
ケース#2:150
ケース#3:150

ヒント

    对于第一组数据,若魔法少女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