其他分享
首页 > 其他分享> > 题解 P7610 【 [THUPC2021] 群星连结】

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

作者:互联网

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