ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 P7610 【 [THUPC2021] 群星连结】

2021-09-11 19:31:40  阅读:229  来源: 互联网

标签:tm ll 题解 hp 回合 num THUPC2021 P7610 技能


0.前言

博客题解传送门

大模拟好评!

特别鸣谢:@shenmadongdong

(具体而言是帮作者调出了两个大错误。)

1.正文

既然是大模拟那么没什么好说的了。

主要分几个部分:

  1. 技能
  2. 普攻
  3. 各种回合加成
  4. 天赋

其中天赋和技能较为类似。

对于普攻,主要需要注意的就是受到伤害以及天赋的加成,算是这几个里面最为简单的一个;

对于技能而言,分 \(10\) 种情况分类讨论即可。

需要注意的是:

  1. 对于受到伤害/产生增减益的效果需要判断这两个先后顺序;
  2. 对于技能 \(10\),所谓的全场不只有自己一队,还有对手的队伍技能也要改为 \(0\) 号技能;
  3. 增/减益型效果,在下面会提到;

个人认为 回合加成 是最容易写错的内容(

一个比较坑的点:对于超过 \(23333\) 回合后的增益效果没有用,可以将其视为只持续到第 \(23333\) 回合为止(除非开大数组,否则会有RE);

对于防御/攻击型的增减益,生效在技能结束(行动结束)后,而结束则是在回合结束。

注意到对手的减益效果也是在自己行动结束后产生的。

易错点:不要忘记在普攻以后增益。(本人错误 \(\times 1\))

而实现方法可以分两个队分别用差分记录。

(当然效果的结束也可以在下回合开始后,\(\texttt{Alice}\) 行动之前处理掉。)

至于每回合都会生效的 \(\texttt{mp}\) 的回复可以直接每回合增加;

最后的效果就是技能 \(10\) 发动后的判断本队死亡的效果,直接在那个回合打上一个 \(\texttt{tag}\) 就可以了。

还有一些其他比较容易错的点:

  1. 攻击的顺序不要写错!(作者就不小心写错了计算伤害的函数调了半天。)
  2. 不要把变量名写错!

2. 代码

讲得这么清楚还要什么代码

剪贴板版本在这里qwq

#include<bits/stdc++.h>
#define N 29
#define T 24009
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
inline ll read() {
    ll x=0,f=1;int c=getchar();
    while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
    while(isdigit(c)) {x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    return x*f;
}
ll n,HP[N],hp[N],MP[N],mp[N],atk[N],def[N],dth[N],Datk[N],Ddef[N];//角色基础
#define A(num) max(atk[num]+Datk[num],1ll)
#define D(num) max(def[num]+Ddef[num],0ll)
ll p[N][N],nw[N];//攻击顺序,包括现在的目标 
ll tf[N],X1[N],Y1[N],skl[N],X2[N],Y2[N],Z2[N];//天赋,技能 
ll t,K[2][T];//记录轮数
ll Dmp[2][T],DAtk[2][T],DDef[2][T],DAtk2[2][T],DDef2[2][T],DDef3[2][T],DAtk3[2][T];
void CMP(ll num){
	if(mp[num]>MP[num]) mp[num]=MP[num];
}
void CHP(ll num){
	if(hp[num]>HP[num]) hp[num]=HP[num];
	if(hp[num]<=0) hp[num]=0,dth[num]=1;
}
ll harm(ll num,ll x,ll y){
	if(tf[num]==1) return (max(x-D(num),0ll)+y-y/2);
	else return (max(x-D(num),0ll)+y);
} 
void mnus(ll num,ll x,ll y){//扣除生命值 
	mp[num]++;
	CMP(num);
	hp[num]-=harm(num,x,y);
	CHP(num);
}
ll ADead(ll tm){//全部死光光 
	for(int i=tm*n+1;i<=tm*n+n;i++)
		if(!dth[i]) return 0;
	return 1;
}
void Norm(ll num){//普通攻击 
	ll tar=p[num][nw[num]];
	if(tf[num]==2) mnus(tar,A(num),X1[num]);
	else if(tf[num]==4) mnus(tar,0,A(num));
	else{
		mnus(tar,A(num),0);
		ll tm=((num-1)/n+1)%2;
		if(tf[num]==5&&!ADead(tm)){hp[num]+=X1[num];CHP(num);} 
	}
	mp[num]++;CMP(num);
}
ll pred(ll num){
	ll tar=p[num][nw[num]];
	if(tf[num]==2){
		ll x=A(num),y=X1[num];
		if(tf[tar]==1) return (max(x-D(tar),0ll)+y-y/2);
		else return (max(x-D(tar),0ll)+y);
	}
	else if(tf[num]==4){
		ll x=0,y=A(num);
		if(tf[tar]==1) return (max(x-D(tar),0ll)+y-y/2);
		else return (max(x-D(tar),0ll)+y);
	}
	else{
		ll y=0,x=A(num);
		if(tf[tar]==1) return (max(x-D(tar),0ll)+y-y/2);
		else return (max(x-D(tar),0ll)+y);
	}
}
void skill(ll num){
	mp[num]=0;
	if(skl[num]==1){
		ll tm=((num-1)/n+1)%2;
		for(int i=tm*n+1;i<=tm*n+n;i++)
			if(!dth[i]) mnus(i,X2[num],0);
		for(int i=tm*n+1;i<=tm*n+n;i++)
			if(!dth[i]) mp[i]-=mp[i]/10;
	} 
	if(skl[num]==2){
		ll tm=((num-1)/n+1)%2;
		for(int i=tm*n+1;i<=tm*n+n;i++)
			if(!dth[i]) mnus(i,0,A(num));
	}
	if(skl[num]==3){
		ll tm=((num-1)/n+1)%2;
		for(int i=tm*n+1;i<=tm*n+n;i++)
			if(!dth[i]) mnus(i,min(HP[i]/10,X2[num]*A(num)),0);
	}
	if(skl[num]==4){
		ll tm=(num-1)/n;
		for(int i=t;i<=min(t+X2[num]-1,23333ll);i++) Dmp[tm][i]+=Y2[num];
	}
	if(skl[num]==5){
		ll tar=p[num][nw[num]];
		Ddef[tar]-=X2[num];
		mnus(tar,0,A(num));
	}
	if(skl[num]==6){
		ll tar=p[num][nw[num]];
		ll tm=((num-1)/n+1)%2;
		mnus(tar,0,A(num));
		DAtk2[tm][t]-=Y2[num];
		DAtk3[tm][min(t+X2[num],23334ll)]+=Y2[num]; 
	}
	if(skl[num]==7){
		ll tm=(num-1)/n;
		ll mn=INF,pp;
		for(int i=tm*n+1;i<=tm*n+n;i++)
			if((!dth[i])&&mn>hp[i]) pp=i,mn=hp[i];
		hp[pp]+=Z2[num];
		CHP(pp);
		DAtk[tm][t]+=Y2[num];
		DAtk3[tm][min(t+X2[num],23334ll)]-=Y2[num];
	}
	if(skl[num]==8){
		ll tm=((num-1)/n+1)%2;
		for(int i=tm*n+1;i<=tm*n+n;i++)
			if(!dth[i]) mnus(i,A(num),0);
		DDef2[tm][t]-=Y2[num];
		DDef3[tm][min(t+X2[num],23334ll)]+=Y2[num];
	}
	if(skl[num]==9){
		ll tm=(num-1)/n;
		for(int i=tm*n+1;i<=tm*n+n;i++)
			if(!dth[i]) hp[i]+=Z2[num],CHP(i);
		DDef[tm][t]+=Y2[num];
		DDef3[tm][min(t+X2[num],23334ll)]-=Y2[num];
	}
	if(skl[num]==10){
		ll tm=(num-1)/n;
		for(int i=tm*n+1;i<=tm*n+n;i++)
			if(!dth[i]){
				atk[i]*=2,def[i]*=2,hp[i]=max(hp[i],HP[i]/2),mp[i]=max(mp[i],MP[i]/2);
			}
		for(int i=1;i<=2*n;i++)
			if(skl[i]==10) skl[i]=0;
		for(int i=t;i<=min(t+X2[num]-1,23333ll);i++) Dmp[tm][i]++;
		K[tm][min(t+X2[num]-1,23334ll)]=1;
	}
	ll tmsf=(num-1)/n;
	ll tmop=((num-1)/n+1)%2;
	for(int i=tmsf*n+1;i<=tmsf*n+n;i++)
		if(!dth[i]){
			Ddef[i]+=DDef[tmsf][t];
			mp[i]+=Dmp[tmsf][t];
			Datk[i]+=DAtk[tmsf][t]; 
			CMP(i);
		}
	for(int i=tmop*n+1;i<=tmop*n+n;i++)
		if(!dth[i])	Datk[i]+=DAtk2[tmop][t],Ddef[i]+=DDef2[tmop][t];
	if(tf[num]==5&&!ADead(tmop)) mp[num]+=Y1[num],CMP(num);
	mp[num]++;CMP(num);
}
int main(){
	//freopen(".in","r",stdin);
	//freopen("game.txt","w",stdout);
	n=read();
	for(int i=1;i<=2*n;i++){
		HP[i]=read();MP[i]=read();
		atk[i]=read();def[i]=read();
		mp[i]=0;hp[i]=HP[i];
		ll tm=((i-1)/n+1)%2;
		for(int j=1;j<=n;j++) p[i][j]=read()+tm*n,nw[i]=1;
		tf[i]=read(),X1[i]=read(),Y1[i]=read();
		skl[i]=read(),X2[i]=read(),Y2[i]=read(),Z2[i]=read();
	}
	while(1){
		t++;
		if(t>23333) break;
		for(int i=0;i<=1;i++)
			for(int j=i*n+1;j<=n+i*n;j++){
				if(!dth[j]){
					Ddef[j]+=DDef3[i][t];
					Datk[j]+=DAtk3[i][t];
				}
			} 
		for(int i=0;i<=1;i++){
			ll mx=0,pp=0;
			for(int j=i*n+1;j<=n*i+n;j++)
				if(mp[j]==MP[j]&&(!dth[j])&&mx<=skl[j]) mx=skl[j],pp=j;
			if(pp!=0) skill(pp);
			else{
				ll mx1=0,mx2=0,p1=0;
				for(int j=i*n+1;j<=n*i+n;j++){
					if((!dth[j])&&mx1<=hp[p[j][nw[j]]]){
						if(mx1==hp[p[j][nw[j]]]){
							if(mx2<=pred(j)) mx1=hp[p[j][nw[j]]],mx2=pred(j),p1=j;	
						}
						else mx1=hp[p[j][nw[j]]],mx2=pred(j),p1=j;
					}
				}	
				Norm(p1);
				ll tmsf=i;
				ll tmop=(i+1)%2;
				for(int j=tmsf*n+1;j<=tmsf*n+n;j++)
					if(!dth[j]){
						Ddef[j]+=DDef[tmsf][t];
						mp[j]+=Dmp[tmsf][t];
						Datk[j]+=DAtk[tmsf][t]; 
						CMP(j);
					}
				for(int j=tmop*n+1;j<=tmop*n+n;j++)
					if(!dth[j])	Datk[j]+=DAtk2[tmop][t],Ddef[j]+=DDef2[tmop][t];
			}
			if(ADead(0)){
				printf("%lld\nBob\n",t);
				for(int i=1+n;i<=n+n;i++) printf("%lld ",hp[i]);
				return 0;
			}
			if(ADead(1)){
				printf("%lld\nAlice\n",t);
				for(int i=1;i<=n;i++) printf("%lld ",hp[i]);
				return 0;
			}
			for(int j=i*n+1;j<=n*i+n;j++)
				if(!dth[j]) mp[j]++,CMP(j);
			for(int j=i*n+1;j<=n*i+n;j++)
				if(!dth[j]&&tf[j]==3) hp[j]+=X1[j],CHP(j),mp[j]+=Y1[j],CMP(j); 
		}
		if(K[0][t]||ADead(0)){
			printf("%lld\nBob\n",t);
			for(int i=1+n;i<=n+n;i++) printf("%lld ",hp[i]);
			break;
		}
		if(K[1][t]||ADead(1)){
			printf("%lld\nAlice\n",t);
			for(int i=1;i<=n;i++) printf("%lld ",hp[i]);
			break;
		}
		for(int i=1;i<=2*n;i++)
			while(dth[p[i][nw[i]]]) nw[i]++;
	}
	return 0;
}

标签:tm,ll,题解,hp,回合,num,THUPC2021,P7610,技能
来源: https://www.cnblogs.com/RollingCode/p/solution-P7610.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有