大模拟

bzoj1033 ZJOI杀蚂蚁

题目大意:根据给定题意模拟游戏过程。

思路:相对比较清晰的大模拟。但因为第一次写这种大模拟,所以还是调试了很久。总结一下这次犯的很多错误:

        1)蚂蚁出生的时候不仅要满足场上不到6只蚂蚁的要求,还要满足(0,0)这个位置没有东西;

        2)在激光塔对拿蛋糕的目标攻击的时候,可能会攻击蚂蚁到线段距离<=0.5(直径为1,半径为0.5)的蚂蚁,这里的判断要十分注意。满足点在端点之间,并且点到直线的距离<=0.5;如果不是对拿蛋糕的目标攻击,就只需要攻击这一个就行了,别的都不符合(按线段式攻击也对,这样会快一些);

        3)在移动的时候,如果这个蚂蚁不能移动,就要把他的上一秒位置统一成这一秒的;

        4)蚂蚁死的时候,会改变队列的头,所以如果平移的这个蚂蚁是target的时候,也要相应的改变target。

#include<iostream>

#include<cstdio>

#include<algorithm>

#include<cstring>

#include<cmath>

#define maxnode 200005

#define inf 2100000000LL

using namespace std;

struct use{

    int old,rank,blood,x,y,ux,uy;

    bool antcake;

}que[maxnode]={0};

int d,r,n,m,s,head,tail,pao[25][2]={0},map[10][10][2]={0},dx[4]={0,1,0,-1},dy[4]={1,0,-1,0},target;

bool cake=false,win=false;

void burn()

{

    que[++tail].old=1;que[tail].rank=(tail+5)/6;que[tail].blood=int(4*pow(1.1,que[tail].rank));

    que[tail].x=que[tail].y=0;que[tail].ux=que[tail].uy=-1;map[0][0][0]=1;que[tail].antcake=false;

}

void leavemessage()

{

    int i,j;

    for (i=head;i<=tail;++i)

        map[que[i].x][que[i].y][1]+=(que[i].antcake ? 5 : 2);

}

bool canmove(int i,int xx,int yy)

{

    if (xx<0||xx>n||yy<0||yy>m) return false;

    if (map[xx][yy][0]==1||(xx==que[i].ux&&yy==que[i].uy)) return false;

    return true;

}

void move()

{

    int i,j,k,maxn,xx,yy;

    for (i=head;i<=tail;++i)

    {

        maxn=-1;

        for (k=0;k<=3;++k)

        {

            xx=que[i].x+dx[k];yy=que[i].y+dy[k];

            if (canmove(i,xx,yy)&&map[xx][yy][1]>maxn) maxn=map[xx][yy][1];

        }

        if (maxn>=0)

        {

            for (k=0;k<=3;++k)

            {

                xx=que[i].x+dx[k];yy=que[i].y+dy[k];

                if (canmove(i,xx,yy)&&map[xx][yy][1]==maxn) break;

            }

            if (que[i].old%5==0)

            {

                k=(k==0?3:k-1);

                while(1)

                {

                    xx=que[i].x+dx[k];yy=que[i].y+dy[k];

                    if (canmove(i,xx,yy)) break;k=(k==0?3:k-1);

                }

            }

            map[que[i].x][que[i].y][0]=0;map[xx][yy][0]=1;

            que[i].ux=que[i].x;que[i].uy=que[i].y;

            que[i].x=xx;que[i].y=yy;

        }

        else {que[i].ux=que[i].x;que[i].uy=que[i].y;}

        if (que[i].x==n&&que[i].y==m&&!cake)

        {

            cake=true;que[i].antcake=true;target=i;k=(int)(4*pow(1.1,que[i].rank));

            que[i].blood=min(k,que[i].blood+k/2);

        }

    }

}

//i炮塔 j蚂蚁 

int fang(int i){return i*i;}

int dis(int i,int j)

{

    int x1,y1,x2,y2;

    x1=pao[i][0];y1=pao[i][1];x2=que[j].x;y2=que[j].y;

    return fang(x1-x2)+fang(y1-y2);

}

bool canattack(int i,int j)

{

    if (dis(i,j)<=r) return true;

    else return false;

}

int disy(int i,int a,int b,int c){return fang(a*que[i].x+b*que[i].y+c);}

void attackone(int i,int j,int kk)

{

    int k,a,b,c,x1,y1,x2,y2;

    if (kk==1) que[j].blood-=d;

    else

    {

      x1=pao[i][0];y1=pao[i][1];x2=que[j].x;y2=que[j].y;

      a=y2-y1;b=x1-x2;c=y1*x2-y2*x1;

      for (k=head;k<=tail;++k)

        if (disy(k,a,b,c)*4<=fang(a)+fang(b)&&

           ((que[k].x>=x1&&que[k].x<=x2)||(que[k].x>=x2&&que[k].x<=x1))&&

           ((que[k].y>=y1&&que[k].y<=y2)||(que[k].y>=y2&&que[k].y<=y1))) 

            que[k].blood-=d;

    }

}

void die(int i)

{

    int j;

    if (target==i){target=0;cake=false;}

    map[que[i].x][que[i].y][0]=0;++head;

    for (j=i;j>=head;--j) {que[j]=que[j-1];if (target==j-1) target=j;}

}

void attack()

{

    int i,j,minn,mini;bool use[25]={false};

    if (target>0)

        for (i=1;i<=s;++i)

            if (canattack(i,target)) {attackone(i,target,0);use[i]=true;}

    for (i=1;i<=s;++i)

        if (!use[i])

        {

            minn=inf;mini=0;use[i]=true;

            for (j=head;j<=tail;++j)

                if (canattack(i,j))

                    if (dis(i,j)<minn){minn=dis(i,j);mini=j;}

            if (mini>0) attackone(i,mini,1);

        }

    for (i=head;i<=tail;++i) 

      if (que[i].blood<0) die(i);

}

void after()

{

    int i,j;

    for (i=head;i<=tail;++i)

        if (que[i].x==0&&que[i].y==0&&que[i].antcake) {win=true;return;}

    for (i=0;i<=n;++i)

      for (j=0;j<=m;++j)

        map[i][j][1]=max(0,map[i][j][1]-1);

    for (i=head;i<=tail;++i) ++que[i].old;

}

void work()

{

    if (tail-head+1<6&&map[0][0][0]==0) burn();

    leavemessage();move();attack();after();

}

int main()

{

    int i,j,t;

    scanf("%d%d%d%d%d",&n,&m,&s,&d,&r);r=r*r;

    for (i=1;i<=s;++i)

    {scanf("%d%d",&pao[i][0],&pao[i][1]);map[pao[i][0]][pao[i][1]][0]=1;}

    scanf("%d",&t);head=1;tail=0;target=0;

    for (i=1;i<=t;++i)

    {

        work();if (win) break;

    }

    if (win) printf("Game over after %d seconds\n",i);

    else printf("The game is going on\n");

    printf("%d\n",tail-head+1);

    for (i=head;i<=tail;++i)

        printf("%d %d %d %d %d\n",que[i].old-1,que[i].rank,que[i].blood,que[i].x,que[i].y);

}
View Code

 

你可能感兴趣的:(模拟)