题解 P9381
小 E 说要有题解,于是就有了题解。
按照题意模拟即可。
代码中始终让
一些需要注意的细节:
- 死人之后被动增益需要重算。
- 不造成伤害的攻击也要输出。
- 不造成生命值增加的回复不能输出。
- 被动回血在回合开始时发动。
- 被动扣血在回合结束时发动。
- 注意浮点数精度。
和考场代码编辑距离不超过 20。
大样例不判主动技能回血时是否形成了实际的数值提升也能过,警钟敲烂。
#include <bits/stdc++.h>
#define int long long
#define double long double
int read()
{
int x=0,f=1,c=getchar();
while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
while(c>47&&c<58)x=x*10+c-48,c=getchar();
return x*f;
}
using namespace std;
struct node
{
char type[23];
int lv,maxhp;
int hp;
double atk,def;
int slv,pslv;
char wtype[23];
double watk;
double ex_skill=1;
double cut;
int remainround;
void in()
{
scanf("%s Lv=%lld maxhp=%lld atk=%Lf def=%Lf skillLv=%lld passivesklLv=%lld %s weaponatk=%Lf",
type,&lv,&maxhp,&atk,&def,&slv,&pslv,wtype,&watk);
// printf("%s %lld %lld %Lf %Lf %lld %lld %s %Lf\n",type,lv,maxhp,atk,def,slv,pslv,wtype,watk);
hp=maxhp;
}
}a[13],b[13];
const int p[]={0,5,3,1,2,4,6,0};
const int ip[]={0,3,4,2,5,1,6,0};
int n=read(),m=read();
double ex_type(node x,node y)
{
char A=x.type[0],B=y.type[0];
int va=0,vb=0;
if(A=='A') va=1;
if(A=='S') va=2;
if(B=='A') vb=1;
if(B=='S') vb=2;
int s=(va+3-vb)%3;
if(s==0) return 1;
else if(s==2) return 0.9;
else return 1.1;
}
double ex_pos(int ap,int dp)
{
int g=(ap+6-dp)%6;
if(g==0) return 1.25;
else if(g==1||g==5) return 1;
else if(g==2||g==4) return 0.75;
else return 0;
}
const double ew_table[]={0,0.013,0.016,0.019,0.022,0.025};
const double ea_table[]={0,0.01,0.02,0.03,0.04,0.05};
const double es_table[]={0,0.01,0.02,0.03,0.04,0.05};
const double sw_table[]={0,0.1,0.12,0.15,0.17,0.2};
const double sa_table[]={0,0.06,0.07,0.08,0.09,0.1};
const double ss_table[]={0,2.1,2.17,2.24,2.32,2.4};
double Aexatk=1,Aexdef=1,Bexatk=1,Bexdef=1;
double heal;
void recalc()
{
heal=0;
Aexatk=Aexdef=Bexatk=Bexdef=1;
for(int i=1; i<=n; ++i) if(a[i].hp>0)
{
if(a[i].type[0]=='W') heal+=ew_table[a[i].pslv];
else if(a[i].type[0]=='A') Aexdef+=ea_table[a[i].pslv];
else Aexatk+=es_table[a[i].pslv];
}
for(int i=1; i<=m; ++i) if(b[i].hp>0)
{
if(b[i].type[0]=='W');
else if(b[i].type[0]=='A') Bexdef+=ea_table[b[i].pslv];
else Bexatk+=es_table[b[i].pslv];
}
heal=min(heal,0.05L),Aexatk=min(Aexatk,1.1L),Aexdef=min(Aexdef,1.1L);
Bexatk=min(Bexatk,1.1L),Bexdef=min(Bexdef,1.1L);
}
const double eps=1e-9;
signed main()
{
for(int i=1; i<=n; ++i) a[i].in();
for(int i=1; i<=m; ++i) b[i].in();
int lsta=0,lstb=0;
int T=read();
char player[]="South";
char rival[]="North";
for(int I=1; I<=T; ++I)
{
recalc();
// cout<<heal<<endl;
for(int i=1; i<=n; ++i) if(a[i].hp>0&&a[i].hp<a[i].maxhp)
{
int qwq=a[i].maxhp*heal+eps;
a[i].hp=min(a[i].maxhp,a[i].hp+qwq);
if(qwq)
printf("%s %lld recovered +%lld hp -> %lld/%lld\n",player,i,qwq,a[i].hp,a[i].maxhp);
}
char str[103];
scanf("%s",str);
int tgt,ap,dp,cur=-1;
for(int i=lsta+1; i<=n; ++i) if(a[i].hp>0){cur=i;break;}
if(cur==-1)for(int i=1; i<=n; ++i) if(a[i].hp>0){cur=i;break;}
lsta=cur;
// for(int i:{5,3,1,2,4,6}) if((i<=m)&&b[i].hp>0) printf("%lld ",i);
// puts("");
if(str[1]=='a') //basic
{
scanf(" target=%lld atkpos=%lld ddgpos=%lld\n",&tgt,&ap,&dp);
int dmg=a[cur].atk*a[cur].watk*Aexatk*ex_type(a[cur],b[tgt])*ex_pos(ap,dp)
*a[cur].ex_skill/b[tgt].def/Bexdef+eps;
b[tgt].hp=max(0ll,b[tgt].hp-dmg);
printf("%s %lld took %lld damage from %s %lld -> %lld/%lld\n",
rival,tgt,dmg,player,cur,b[tgt].hp,b[tgt].maxhp);
a[cur].ex_skill=1;
}
else if(str[1]=='p') //special
{
scanf(" target=%lld atkpos=%lld ddgpos=%lld\n",&tgt,&ap,&dp);
// double dmg=
if(a[cur].wtype[0]=='B')
{
int dmg=a[cur].atk*a[cur].watk*Aexatk*ex_type(a[cur],b[tgt])*ex_pos(ap,dp)
*a[cur].ex_skill/b[tgt].def/Bexdef*1.25+eps;
b[tgt].hp=max(0ll,b[tgt].hp-dmg);
printf("%s %lld took %lld damage from %s %lld -> %lld/%lld\n",
rival,tgt,dmg,player,cur,b[tgt].hp,b[tgt].maxhp);
}
else if(a[cur].wtype[0]=='G')
{
int left=ip[tgt]-1,right=ip[tgt]+1;
while(left>=1&&(p[left]>m||b[p[left]].hp<=0)) --left;
while(right<=6&&(p[right]>m||b[p[right]].hp<=0)) ++right;
if(right>6) right=0;
left=p[left],right=p[right];
// printf("%d %d\n",left,right);
int z=(left>0)+(right>0)+1;
int dmg=a[cur].atk*a[cur].watk
*Aexatk*ex_type(a[cur],b[tgt])*ex_pos(ap,dp)
*a[cur].ex_skill*1.35
/b[tgt].def/Bexdef/z+eps;
b[tgt].hp=max(0ll,b[tgt].hp-dmg);
printf("%s %lld took %lld damage from %s %lld -> %lld/%lld\n",
rival,tgt,dmg,player,cur,b[tgt].hp,b[tgt].maxhp);
tgt=left;
if(tgt)
{
recalc();
int dmg=a[cur].atk*a[cur].watk*Aexatk*ex_type(a[cur],b[tgt])*ex_pos(ap,dp)
*a[cur].ex_skill*1.35/b[tgt].def/Bexdef/z+eps;
b[tgt].hp=max(0ll,b[tgt].hp-dmg);
printf("%s %lld took %lld damage from %s %lld -> %lld/%lld\n",
rival,tgt,dmg,player,cur,b[tgt].hp,b[tgt].maxhp);
}
tgt=right;
if(tgt)
{
recalc();
int dmg=a[cur].atk*a[cur].watk*Aexatk*ex_type(a[cur],b[tgt])*ex_pos(ap,dp)
*a[cur].ex_skill*1.35/b[tgt].def/Bexdef/z+eps;
b[tgt].hp=max(0ll,b[tgt].hp-dmg);
printf("%s %lld took %lld damage from %s %lld -> %lld/%lld\n",
rival,tgt,dmg,player,cur,b[tgt].hp,b[tgt].maxhp);
}
}
else
{
int left=ip[tgt]-1,right=ip[tgt]+1;
while(left>=1&&(p[left]>m||b[p[left]].hp<=0)) --left;
while(right<=6&&(p[right]>m||b[p[right]].hp<=0)) ++right;
if(right>6) right=0;
left=p[left],right=p[right];
int dmg=a[cur].atk*a[cur].watk*Aexatk*ex_type(a[cur],b[tgt])*ex_pos(ap,dp)
*a[cur].ex_skill*1.15/b[tgt].def/Bexdef+eps;
b[tgt].hp=max(0ll,b[tgt].hp-dmg);
printf("%s %lld took %lld damage from %s %lld -> %lld/%lld\n",
rival,tgt,dmg,player,cur,b[tgt].hp,b[tgt].maxhp);
tgt=left;
if(tgt)
{
recalc();
int dmg=a[cur].atk*a[cur].watk*Aexatk*ex_type(a[cur],b[tgt])*ex_pos(ap,dp)
*a[cur].ex_skill*0.23/b[tgt].def/Bexdef+eps;
b[tgt].hp=max(0ll,b[tgt].hp-dmg);
printf("%s %lld took %lld damage from %s %lld -> %lld/%lld\n",
rival,tgt,dmg,player,cur,b[tgt].hp,b[tgt].maxhp);
}
tgt=right;
if(tgt)
{
recalc();
int dmg=a[cur].atk*a[cur].watk*Aexatk*ex_type(a[cur],b[tgt])*ex_pos(ap,dp)
*a[cur].ex_skill*0.23/b[tgt].def/Bexdef+eps;
b[tgt].hp=max(0ll,b[tgt].hp-dmg);
printf("%s %lld took %lld damage from %s %lld -> %lld/%lld\n",
rival,tgt,dmg,player,cur,b[tgt].hp,b[tgt].maxhp);
}
}
a[cur].ex_skill=1;
}
else //skill
{
scanf(" target=%lld\n",&tgt);
if(a[cur].slv!=0){
if(a[cur].type[0]=='W')
{
printf("%s %lld applied %s skill to %s %lld\n",player,cur,a[cur].type,player,tgt);
int qwq=a[tgt].maxhp*sw_table[a[cur].slv]+eps;
bool ok=(a[tgt].hp==a[tgt].maxhp);
a[tgt].hp=min(a[tgt].maxhp,a[tgt].hp+qwq);
if(qwq&&ok==0)
printf("%s %lld recovered +%lld hp -> %lld/%lld\n",player,tgt,qwq,a[tgt].hp,a[tgt].maxhp);
}
else if(a[cur].type[0]=='A')
{
printf("%s %lld applied %s skill to %s %lld\n",player,cur,a[cur].type,rival,tgt);
b[tgt].cut=sa_table[a[cur].slv];
b[tgt].remainround=3;
}
else
{
printf("%s %lld applied %s skill to %s %lld\n",player,cur,a[cur].type,player,tgt);
a[tgt].ex_skill=ss_table[a[cur].slv];
}}
}
for(int i=1; i<=m; ++i)
{
if(b[i].remainround>0&&b[i].hp>0)
{
int qwq=b[i].cut*b[i].maxhp+eps;
--b[i].remainround,
b[i].hp=max(b[i].hp-qwq,0ll);
printf("%s %lld took %lld damage from skill -> %lld/%lld\n",rival,i,qwq,b[i].hp,b[i].maxhp);
}
}
if(rival[0]=='S')
{
printf("North: ");
for(int i:{5,3,1,2,4,6})
if(i<=n) printf("%lld/%lld ",a[i].hp,a[i].maxhp);
puts("");printf("South: ");
for(int i:{5,3,1,2,4,6})
if(i<=m) printf("%lld/%lld ",b[i].hp,b[i].maxhp);
}
else
{
printf("North: ");
for(int i:{5,3,1,2,4,6})
if(i<=m) printf("%lld/%lld ",b[i].hp,b[i].maxhp);
puts("");printf("South: ");
for(int i:{5,3,1,2,4,6})
if(i<=n) printf("%lld/%lld ",a[i].hp,a[i].maxhp);
}
puts("");puts("");
swap(a,b),swap(lsta,lstb),swap(n,m);
swap(rival,player);
}
bool win=1;
for(int i=1; i<=n; ++i) win&=(a[i].hp==0);
if(win) printf("Team %s won.",rival);
return 0;
}