2964: Boss单挑战

Description

  某RPG游戏中,最后一战是主角单挑Boss,将其简化后如下:
  主角的气血值上限为HP,魔法值上限为MP,愤怒值上限为SP;Boss仅有气血值,其上限为M。
  现在共有N回合,每回合都是主角先行动,主角可做如下选择之一:
  1. 普通攻击:减少对方X的气血值,并增加自身DSP的愤怒值。(不超过上限)
  2. 法术攻击:共有N1种法术,第i种消耗Bi的魔法值,减少对方Yi的气血值。(使用时要保证MP不小于Bi)
  3. 特技攻击:共有N2种特技,第i种消耗Ci的愤怒值,减少对方Zi的气血值。(使用时要保证SP不小于Ci)
  4. 使用HP药水:增加自身DHP的气血值。(不超过上限)
  5. 使用MP药水:增加自身DMP的魔法值。(不超过上限)
  之后Boss会攻击主角,在第i回合减少主角Ai的气血值。
  刚开始时气血值,魔法值,愤怒值都是满的。当气血值小于等于0时死亡。
  如果主角能在这N个回合内杀死Boss,那么先输出“Yes”,之后在同一行输出最早能在第几回合杀死Boss。(用一个空格隔开)
  如果主角一定会被Boss杀死,那么输出“No”。
  其它情况,输出“Tie”。

Input

  输入的第一行包含一个整数T,为测试数据组数。
  接下来T部分,每部分按如下规则输入:
  第一行九个整数N, M, HP, MP, SP, DHP, DMP, DSP, X。
  第二行N个整数Ai。
  第三行第一个整数N1,接下来包含N1对整数Bi, Yi。
  第四行第一个整数N2,接下来包含N2对整数Ci, Zi。

Output

  输出共包含T行,每行依次对应输出一个答案。

题解:

因为三种攻击互不干扰所以,我们可以分别DP。

具体转移看代码吧。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cstring>
#define INF 0x3f3f3f3f
using namespace std;
const int N=1010;
int T;
int n,m,hp,mp,sp,dhp,dmp,x,n1,n2,dsp;
int a[N];
int B[N],Y[N],C[N],Z[N];
int fmp[N][N];//第i回合还剩j魔法值的最大魔法攻击力
int fsp[N][N];//第i回合还剩j怒气值的最大特技攻击力
int dpmp[N],dpsp[N];//不管剩多少mp,sp值的最大攻击力 
int dphp[N][N];//第i回合还剩jhp的最大攻击次数 
int main()
{
	scanf("%d",&T);
	while(T--)
	{
		int flag=0;
		 memset(fmp,0,sizeof(fmp));
         memset(fsp,0,sizeof(fsp));
         memset(dpmp,0,sizeof(dpmp));
         memset(dpsp,0,sizeof(dpsp));
         memset(dphp,-INF,sizeof(dphp));
		scanf("%d%d%d%d%d%d%d%d%d",&n,&m,&hp,&mp,&sp,&dhp,&dmp,&dsp,&x);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);//boss攻击
		scanf("%d",&n1);
		for(int i=1;i<=n1;i++) scanf("%d%d",&B[i],&Y[i]);//魔法攻击,消耗的魔法值,打掉的hp
		scanf("%d",&n2);
		for(int i=1;i<=n2;i++) scanf("%d%d",&C[i],&Z[i]);//特技,消耗怒气,打掉HP
		for(int i=0;i<=n;i++)
		{
			for(int j=0;j<=mp;j++)
			dpmp[i]=max(fmp[i][j],dpmp[i]);
			if(i<n)
			{
				for(int j=0;j<=mp;j++)
				{
					fmp[i+1][min(mp,j+dmp)]=max(fmp[i+1][min(mp,j+dmp)],fmp[i][j]);

					for(int k=1;k<=n1;k++)
					if(j-B[k]>=0)
					fmp[i+1][j-B[k]]=max(fmp[i+1][j-B[k]],fmp[i][j]+Y[k]);
				}
			}
		}
		for(int i=0;i<=n;i++)
		{
			for(int j=0;j<=sp;j++)
			dpsp[i]=max(fsp[i][j],dpsp[i]);
			if(i<n)
			{
				for(int j=0;j<=sp;j++)
				{
					fsp[i+1][min(sp,j+dsp)]=max(fsp[i+1][min(sp,j+dsp)],fsp[i][j]+x);
					 for(int k=1;k<=n2;k++)
					if(j-C[k]>=0)
					fsp[i+1][j-C[k]]=max(fsp[i+1][j-C[k]],fsp[i][j]+Z[k]);
				}
			}
		}
		int minn=INF;
		for(int i=0;i<=n;i++)
		{
			for(int j=0;j<=n;j++)
			{
				if(dpsp[i]+dpmp[j]>=m)
				minn=min(minn,i+j);
			}
		}
		//printf("%d\n",minn);
		dphp[1][hp]=1;
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=hp;j++)
			{
				if(dphp[i][j]>=minn)
				{
					printf("Yes %d\n",i);
					flag=1;
					break;
				}
			}
			if(flag==1) break;
			for(int j=1;j<=hp;j++)
			{
				   if(min(j+dhp,hp)>a[i])
					dphp[i+1][min(j+dhp,hp)-a[i]]=max(dphp[i+1][min(j+dhp,hp)-a[i]],dphp[i][j]);
					if(j-a[i]>0)
					dphp[i+1][j-a[i]]=max(dphp[i+1][j-a[i]],dphp[i][j]+1); 
			}
		}
		if(flag==1) continue;
		for(int i=1;i<=hp;i++)
		if(dphp[n+1][i]>=0)
		{
			printf("Tie\n");
			flag=1;
			break;
		}
		if(flag==1) continue;
		printf("No\n");
      
	}
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值