Luogu2586 [ZJOI2008]杀蚂蚁

https://www.luogu.com.cn/problem/P2586

模拟

按题意模拟

注意点:

\(1.\)判断激光是否会打到其他蚂蚁的判断要小心(计算几何基础都不扎实),实际上我的的代码中不是很科学,应当算出与直线与圆的交点然后判断,而我直接判断圆心是否夹在线段的两个端点中间,但是在本题中,如果圆心恰好与线段端点在同一水平(或垂直)线上,那么它显然比我们找到的点与塔更近,矛盾

\(2.\)当蚂蚁年龄为\(5\)的倍数时,蚂蚁的转向仍然要满足不回到原来位置

\(3.\)当扛着蛋糕的蚂蚁被杀死后,如果在\((n,m)\)的蚂蚁在下一秒无法运动,那么它将拿到蛋糕

\(4.\)当一只蚂蚁在这一轮无法动时,它的上一次方向要丢弃

\(Code:\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define N 9
#define check(x,y) (x>=0 && x<=n && y>=0 && y<=m && !a[x][y].kd)
#define K(x,y) a[x][y].kd
#define I(x,y) a[x][y].id
#define im(x,y) a[x][y].xxs
#define lst(x) ant[x].tag
#define old(x) ant[x].od
#define le(x) ant[x].lev
#define bl(x) ant[x].blood
#define fbl(x) ant[x].fblood
#define L(x) ant[x].l
#define R(x) ant[x].r
#define cake(x) ant[x].ck
#define D double
using namespace std;
int n,m,x,y,s,d,c,kr,sqrkr,T,rc,cnt,e[25][2];
int dic[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
bool die[10];
D le_bl=4.0;
bool flag=false;
struct Ant
{
    int tag=-8;
    int od,lev,blood,fblood,l,r;
    bool ck=false;
    void set0()
    {
        tag=-8,od=lev=blood=fblood=l=r=0,ck=false;
    }
}ant[10],rant[10];
struct node
{
    int kd=0,id,xxs=0;
    node (int kk=0,int ii=0)
    {
        kd=kk,id=ii;
    }
}a[N][N];
void New_Ant()
{
    if (cnt>=6 || K(0,0)!=0)
        return;
    rc++,cnt++;
    K(0,0)=2;
    I(0,0)=cnt;
    if ((rc-1)%6==0)
        le_bl*=1.1;
    ant[cnt].set0();
    le(cnt)=(rc-1)/6+1;
    fbl(cnt)=bl(cnt)=(int)le_bl;
}
void Left_Information()
{
    for (int i=1;i<=cnt;i++)
        if (cake(i))
            im(L(i),R(i))+=5; else
            im(L(i),R(i))+=2;
}
void Get_Cake(int x)
{
    if (c)
        return;
    if (L(x)==n && R(x)==m)
    {
        cake(x)=true;
        bl(x)+=fbl(x) >> 1;
        if (bl(x)>fbl(x))
            bl(x)=fbl(x);
        c=x;
    }
}
void Move_One_Ant(int x)
{
    int mxx=-1,qr;
    for (int i=0;i<4;i++)
        if (abs(i-lst(x))!=2)
        {
            int nl=L(x)+dic[i][0];
            int nr=R(x)+dic[i][1];
            if (!check(nl,nr))
                continue;
            if (im(nl,nr)>mxx)
            {
                mxx=im(nl,nr);
                qr=i;
            }
        }
    if (mxx==-1)
    {
        lst(x)=-8;
        Get_Cake(x);
        return;
    }
    if ((old(x)+1)%5==0)
    {
        int nx=qr-1;
        if (nx==-1)
            nx=3;
        bool t=false;
        for (;;)
        {
            int nl=L(x)+dic[nx][0];
            int nr=R(x)+dic[nx][1];
            if (check(nl,nr) && abs(nx-lst(x))!=2)
            {
                qr=nx;
                break;
            }
            nx--;
            if (nx==-1)
                nx=3;
        }
    }
    lst(x)=qr;
    int nl=L(x)+dic[qr][0];
    int nr=R(x)+dic[qr][1];
    K(L(x),R(x))=0,I(nl,nr)=0;
    K(nl,nr)=2,I(nl,nr)=x;
    L(x)=nl,R(x)=nr;
    Get_Cake(x);
}
void Ant_Move()
{
    for (int i=1;i<=cnt;i++)
        Move_One_Ant(i);
}
int SqrDis(int x,int y,int c)
{
    return (x-L(c))*(x-L(c))+(y-R(c))*(y-R(c));
}
bool Mid(int x,int y,int c,int d)
{
    if (x<L(c) && L(c)<L(d))
        return true;
    if (L(d)<L(c) && L(c)<x)
        return true;
    if (y<R(c) && R(c)<R(d))
        return true;
    if (R(d)<R(c) && R(c)<y)
        return true;
    if (L(c)<x && x<L(d))
        return true;
    if (L(c)>x && x>L(d))
        return true;
    if (R(c)<y && y<R(d))
        return true;
    if (R(c)>y && y>R(d))
        return true;
    return false;
}
D Dis_Point_To_Line(D x0,D y0,D A,D B,D C)
{
    return fabs(((D)A*x0+(D)B*y0+C)/sqrt(A*A+B*B));
}
void Get_Line(D &A,D &B,D &C,D x,D y,D x0,D y0)
{
    if (x==x0)
    {
        A=1,B=0,C=-x;
        return;
    }
    if (y==y0)
    {
        A=0,B=1,C=-y;
        return;
    }
    D k,b;
    k=(y0-y)/(x0-x);
    b=y-k*x;
    A=-k,B=1,C=-b;
}
bool On_Line(D A,D B,D C,D x,D y)
{
    return A*x+B*y+C==0;
}
void Kill(int x,int y,int c)
{
    D A,B,C;
    Get_Line(A,B,C,x,y,L(c),R(c));
    for (int i=1;i<=cnt;i++)
        if (Dis_Point_To_Line(L(i),R(i),A,B,C)<=0.5 && !Mid(x,y,c,i))
            bl(i)-=d;
}
void Use_Tower(int x,int y)
{
    if (c && SqrDis(x,y,c)<=sqrkr)
    {
        Kill(x,y,c);
        return;
    }
    int mxdis=6662333,kid=0;
    for (int i=1;i<=cnt;i++)
        if (SqrDis(x,y,i)<=sqrkr && SqrDis(x,y,i)<mxdis)
            mxdis=SqrDis(x,y,i),kid=i;
    if (!kid)
        return;
    Kill(x,y,kid);
}
void Tower_Kill()
{
    for (int i=1;i<=s;i++)
        Use_Tower(e[i][0],e[i][1]);
}
bool Dead(int x)
{
    return bl(x)<0;
}
void Deal_With_Dead_Ant()
{
    int recnt=0;
    for (int i=1;i<=cnt;i++)
        if (!Dead(i))
        {
            rant[++recnt]=ant[i];
            if (cake(i))
                c=recnt;
        } else
        {
            if (cake(i))
                c=0;
            K(L(i),R(i))=0;
        }
    cnt=recnt;
    for (int i=1;i<=recnt;i++)
        ant[i]=rant[i];
}
void Put_Answer(int TT)
{
    if (TT)
        printf("Game over after %d seconds\n",TT); else
        printf("The game is going on\n");
    printf("%d\n",cnt);
    for (int i=1;i<=cnt;i++)
        printf("%d %d %d %d %d\n",old(i),le(i),bl(i),L(i),R(i));
}
void Lose_Or_Not(int TT)
{
    if (c && !L(c) && !R(c))
    {
        Put_Answer(TT);
        exit(0);
    }
}
void Modify_Imformation()
{
    for (int i=0;i<=n;i++)
        for (int j=0;j<=m;j++)
            if (im(i,j))
                im(i,j)--;
    for (int i=1;i<=cnt;i++)
        old(i)++;
}
void Type_Ant(int TT=0)
{
    putchar('\n');
    printf("Ant %d:\n",TT);
    for (int i=1;i<=cnt;i++)
        printf("%d %d %d %d %d\n",old(i),le(i),bl(i),L(i),R(i));
}
void Type_Im(int TT=0)
{
    putchar('\n');
    printf("Im %d:\n",TT);
    for (int i=0;i<=n;i++)
    {
        for (int j=0;j<=m;j++)
            printf("%d ",im(i,j));
        putchar('\n');
    }
}
void Type_Map(int TT=0)
{
    putchar('\n');
    printf("Map %d:\n",TT);
    for (int i=0;i<=n;i++)
    {
        for (int j=0;j<=m;j++)
            printf("%d ",K(i,j));
        putchar('\n');
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    scanf("%d%d%d",&s,&d,&kr);
    sqrkr=kr*kr;
    for (int i=1;i<=s;i++)
    {
        scanf("%d%d",&e[i][0],&e[i][1]);
        a[e[i][0]][e[i][1]]=node(1,0);
    }
    scanf("%d",&T);
    for (int TT=1;TT<=T;TT++)
    {
        New_Ant();
        Left_Information();
        Ant_Move();
        Tower_Kill();
        Deal_With_Dead_Ant();
        Lose_Or_Not(TT);
        Modify_Imformation();
    }
    Put_Answer(0);
    return 0;
}
posted @ 2020-09-18 19:06  GK0328  阅读(227)  评论(0编辑  收藏  举报