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); }