题解 P9381

· · 题解

小 E 说要有题解,于是就有了题解。

按照题意模拟即可。

代码中始终让 a 代表当前行动的一方。

一些需要注意的细节:

和考场代码编辑距离不超过 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;
}