题解 P7610 【 [THUPC2021] 群星连结】
作者:互联网
0.前言
大模拟好评!
特别鸣谢:@shenmadongdong。
(具体而言是帮作者调出了两个大错误。)
1.正文
既然是大模拟那么没什么好说的了。
主要分几个部分:
- 技能
- 普攻
- 各种回合加成
- 天赋
其中天赋和技能较为类似。
对于普攻,主要需要注意的就是受到伤害以及天赋的加成,算是这几个里面最为简单的一个;
对于技能而言,分 \(10\) 种情况分类讨论即可。
需要注意的是:
- 对于受到伤害/产生增减益的效果需要判断这两个先后顺序;
- 对于技能 \(10\),所谓的全场不只有自己一队,还有对手的队伍技能也要改为 \(0\) 号技能;
- 增/减益型效果,在下面会提到;
个人认为 回合加成 是最容易写错的内容(
一个比较坑的点:对于超过 \(23333\) 回合后的增益效果没有用,可以将其视为只持续到第 \(23333\) 回合为止(除非开大数组,否则会有RE);
对于防御/攻击型的增减益,生效在技能结束(行动结束)后,而结束则是在回合结束。
注意到对手的减益效果也是在自己行动结束后产生的。
易错点:不要忘记在普攻以后增益。(本人错误 \(\times 1\))
而实现方法可以分两个队分别用差分记录。
(当然效果的结束也可以在下回合开始后,\(\texttt{Alice}\) 行动之前处理掉。)
至于每回合都会生效的 \(\texttt{mp}\) 的回复可以直接每回合增加;
最后的效果就是技能 \(10\) 发动后的判断本队死亡的效果,直接在那个回合打上一个 \(\texttt{tag}\) 就可以了。
还有一些其他比较容易错的点:
- 攻击的顺序不要写错!(作者就不小心写错了计算伤害的函数调了半天。)
- 不要把变量名写错!
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