- ACM
【[ZJOI]杀蚂蚁】
- 2024-6-24 22:20:51 @
#include <bits/stdc++.h> using namespace std; const double eps=1e-10; const int MAXN=10; int n,m,s,d,t; double r; int antCnt; int nowt; int dirx[4]={0,1,0,-1}; int diry[4]={1,0,-1,0}; int totalSpawn; bool cakeBeTaken; double prepow[35000]; struct mpNode { int message=0; bool canMove=true; }; struct antNode { int age; int level; int HP; int posx; int posy; int prex; int prey; int maxHP; bool isCake; antNode(int age,int level,int HP,int x,int y,bool isCake=false): age(age),level(level),HP(HP),posx(x),posy(y),isCake(isCake),prex(x),prey(y),maxHP(HP){} }; struct towerNode { int x; int y; double minDis; bool haveTarget; bool haveCakeTarget; list<antNode>::iterator target; }; mpNode mp[MAXN][MAXN]; list<antNode> antList; towerNode tower[22]; inline int read() { int x=0,f=1;char ch=getchar(); while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();} while (isdigit(ch)){x=x\*10+ch-48;ch=getchar();} return x\*f; } struct Point { double x; double y; }; Point inline TurnPoint(double x,double y) { Point NewPoint; NewPoint.x=x; NewPoint.y=y; return NewPoint; } Point operator +(Point A,Point B) { Point NewPoint=TurnPoint(A.x+B.x,A.y+B.y); return NewPoint; } Point operator -(Point A,Point B) { Point NewPoint=TurnPoint(A.x-B.x,A.y-B.y); return NewPoint; } inline int DoublePositive(double x) { if(fabs(x)<eps) return 0; if(x<0) return -1; return 1; } inline double Dot(Point A,Point B) { double sum=A.x\*B.x+A.y\*B.y; return sum; } inline double Length(Point A) { double sum=sqrt(Dot(A,A)); return sum; } inline double Cross(Point A,Point B) { double sum=A.x\*B.y-A.y\*B.x; return sum; } inline double GetSlope(Point A) { double sum=A.y/A.x; return sum; } inline double GetPointDistantToSegment(Point P,Point A,Point B) { Point Vector\_1=B-A; Point Vector\_2=P-A; Point Vector\_3=P-B; if(DoublePositive(Dot(Vector\_1,Vector\_2))<0) return Length(Vector\_2); if(DoublePositive(Dot(Vector\_1,Vector\_3))>0) return Length(Vector\_3); return fabs(Cross(Vector\_1,Vector\_2)/Length(Vector\_1)); } inline double GetDistance(double tx,double ty,double ax,double ay) { return sqrt((tx-ax)\*(tx-ax)+(ty-ay)\*(ty-ay)); } inline void AntSpawn() { if(antCnt>=6||mp[0][0].canMove==false) return; antCnt++; totalSpawn++; int nowLevel=((totalSpawn-1)/6)+1; antList.push\_back(antNode(0,nowLevel,(int)(4.0\*prepow[nowLevel]),0,0,false)); mp[0][0].canMove=false; return; } inline void LeaveMessage() { list<antNode>::iterator it; for(it=antList.begin();it!=antList.end();it++) { if(it->isCake==true) mp[it->posx][it->posy].message+=5; else mp[it->posx][it->posy].message+=2; } return; } inline void Move() { list<antNode>::iterator it; for(it=antList.begin();it!=antList.end();it++) { int pos; int ccMaxMessage=0; int chooseCount=0; for(int i=0;i<4;i++) { int ccx=it->posx+dirx[i],ccy=it->posy+diry[i]; if(mp[ccx][ccy].canMove==true&&(ccx!=it->prex||ccy!=it->prey)&&ccx>=0&&ccx<=n&&ccy>=0&&ccy<=m) { if(mp[ccx][ccy].message==ccMaxMessage) { pos=i; chooseCount++; } else if(mp[ccx][ccy].message>ccMaxMessage) { ccMaxMessage=mp[ccx][ccy].message; pos=i; chooseCount=1; } } } if(chooseCount==0) { it->prex=it->posx; it->prey=it->posy; continue; } else if(chooseCount>1) { for(pos=0;pos<4;pos++) { int ccx=it->posx+dirx[pos],ccy=it->posy+diry[pos]; if(mp[ccx][ccy].canMove==true&&(ccx!=it->prex||ccy!=it->prey)&&ccx>=0&&ccx<=n&&ccy>=0&&ccy<=m&&mp[ccx][ccy].message==ccMaxMessage) break; } } if((it->age+1)%5==0) { for(int i=0;i<4;i++) { pos--; if(pos<0) pos+=4; int ccx=it->posx+dirx[pos],ccy=it->posy+diry[pos]; if(mp[ccx][ccy].canMove==true&&(ccx!=it->prex||ccy!=it->prey)&&ccx>=0&&ccx<=n&&ccy>=0&&ccy<=m) break; } } it->prex=it->posx; it->prey=it->posy; it->posx+=dirx[pos]; it->posy+=diry[pos]; mp[it->prex][it->prey].canMove=true; mp[it->posx][it->posy].canMove=false; } return; } inline void GetCake() { list<antNode>::iterator it; for(it=antList.begin();it!=antList.end();it++) { if(it->posx==n&&it->posy==m&&cakeBeTaken==false) { cakeBeTaken=true; it->isCake=true; it->HP=min(it->HP+(int)(floor)((double)it->maxHP/2.0),it->maxHP); } } return; } inline void TowerAttack() { list<antNode>::iterator it; for(int i=1;i<=s;i++) { tower[i].haveTarget=false; tower[i].minDis=99999999; tower[i].haveCakeTarget=false; for(it=antList.begin();it!=antList.end();it++) { double dis=GetDistance(tower[i].x,tower[i].y,it->posx,it->posy); if(dis-r<=eps) { tower[i].haveTarget=true; if(it->isCake) { tower[i].haveCakeTarget=true; tower[i].target=it; } else if(dis<tower[i].minDis&&tower[i].haveCakeTarget==false) { tower[i].target=it; tower[i].minDis=dis; } } if(tower[i].haveCakeTarget) break; } } for(int i=1;i<=s;i++) { if(tower[i].haveTarget==false) continue; if(tower[i].haveCakeTarget==false) tower[i].target->HP-=d; else { Point A=TurnPoint(tower[i].target->posx,tower[i].target->posy); Point B=TurnPoint(tower[i].x,tower[i].y); for(it=antList.begin();it!=antList.end();it++) { if(it->isCake) { it->HP-=d; continue; } Point P=TurnPoint(it->posx,it->posy); double QAQDistance=GetPointDistantToSegment(P,A,B); if(QAQDistance-0.5<eps) it->HP-=d; } } } return; } inline void DestoryBody() { bool isErase=false; list<antNode>::iterator it; for(it=antList.begin();it!=antList.end();it++) { if(isErase==true) { it=antList.begin(); isErase=false; } if(it->HP<0) { if(it->isCake) { it->isCake=false; cakeBeTaken=false; } mp[it->posx][it->posy].canMove=true; antList.erase(it); antCnt--; isErase=true; } } return; } inline bool GameOverCheck() { list<antNode>::iterator it; for(it=antList.begin();it!=antList.end();it++) if(it->isCake==true&&it->HP>=0&&it->posx==0&&it->posy==0) return true; return false; } inline void LastUpdate() { for(int i=0;i<=n;i++) for(int j=0;j<=m;j++) if(mp[i][j].message) mp[i][j].message--; list<antNode>::iterator it; for(it=antList.begin();it!=antList.end();it++) it->age++; return; } inline void print() { if(nowt==t+1) cout<<"The game is going on"<<endl; else cout<<"Game over after "<<nowt<<" seconds"<<endl; list<antNode>::iterator it; cout<<antCnt<<endl; for(it=antList.begin();it!=antList.end();it++) cout<<it->age<<" "<<it->level<<" "<<it->HP<<" "<<it->posx<<" "<<it->posy<<endl; } int main() { totalSpawn=0; cakeBeTaken=false; antCnt=0; n=read(),m=read(),s=read(),d=read(),r=read(); for(int i=1;i<=s;i++) { tower[i].x=read(); tower[i].y=read(); mp[tower[i].x][tower[i].y].canMove=false; } t=read(); prepow[1]=1.1; for(int i=2;i<=(t/6)+1;i++) prepow[i]=prepow[i-1]\*1.1; for(nowt=1;nowt<=t;nowt++) { AntSpawn(); LeaveMessage(); Move(); GetCake(); TowerAttack(); DestoryBody(); if(GameOverCheck()) break; LastUpdate(); } print(); return 0; }