【模拟】【计算几何】[ZJOI2008][HYSBZ/BZOJ1033]杀蚂蚁antbuster
题目链接
分析
这道题,是一道十分优(e)秀(xin)的模拟题。
有一些注意事项:
- 一边看题一边写,不要把题目读错了
- 一切活动都要严格按照这个顺序来,仔细理解题目所给的意思。
- 注意蚂蚁移动的顺序。
- 所有炮塔是同时攻击的。
- 在模拟中掺杂了计算几何。
知道了这些,写不写得出来,就看你的实(ren)力(pin)了。
代码
#include<cstdio>
#include<algorithm>
#include<set>
#include<iostream>
#include<cmath>
#include<stack>
#define MAXS 20
#define INF 0x7fffffff
#define MAXN 8
using namespace std;
#define MAXT 200000
set<int>se;
int n,m,s,d,r,x[MAXS+10],y[MAXS+10],cnt,b[MAXT+10],t,f[MAXN+10][MAXN+10],cake,num,bt[MAXT+10];
double k1,b1,mypow[MAXT+10];
pair<int,int>pos[MAXT+10],fr[MAXT+10];
int mat[MAXN+10][MAXN+10],dir[4][2]={{0,1},{1,0},{0,-1},{-1,0}},tms;
void Read(int &x){
char c;
while(c=getchar(),c!=EOF)
if(c>='0'&&c<='9'){
x=c-'0';
while(c=getchar(),c>='0'&&c<='9')
x=x*10+c-'0';
ungetc(c,stdin);
return;
}
}
void read(){
int i;
Read(n),Read(m),Read(s),Read(d),Read(r);
for(i=1;i<=s;i++){
Read(x[i]),Read(y[i]);
mat[x[i]][y[i]]=-1;
}
Read(t);
}
inline int Get_sqdist(int x1,int y1,int x2,int y2){
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
inline double Get_dist(int x1,int y1,int x2,int y2){
return sqrt(Get_sqdist(x1,y1,x2,y2));
}
void born(){
if(cnt<6&&!mat[0][0]){
num++;
cnt++;
bt[num]=tms;
mat[0][0]=num;
pos[num]=make_pair(0,0);
b[num]=4*mypow[(num+5)/6];
se.insert(num);
}
}
void move(){
int tx,ty,d,mx,maxdir,ttx,tty,cc;
set<int>::iterator j;
for(j=se.begin();j!=se.end();j++){
tx=pos[*j].first,ty=pos[*j].second;
f[tx][ty]+=(*j==cake?5:2);
mx=-1,maxdir=-1,cc=0;
for(d=0;d<4;d++){
ttx=tx+dir[d][0],tty=ty+dir[d][1];
if(ttx>=0&&ttx<=n&&tty>=0&&tty<=m&&!mat[ttx][tty]&&fr[*j]!=make_pair(ttx,tty))
if(f[ttx][tty]>mx)
maxdir=d,mx=f[ttx][tty];
}
if(maxdir==-1){
fr[*j]=pos[*j];
continue;
}
if((tms-bt[*j]+1)%5==0)
for(maxdir=(maxdir+3)%4;;maxdir=(maxdir+3)%4){
ttx=tx+dir[maxdir][0],tty=ty+dir[maxdir][1];
if(ttx>=0&&ttx<=n&&tty>=0&&tty<=m&&!mat[ttx][tty]&&fr[*j]!=make_pair(ttx,tty))
break;
}
fr[*j]=pos[*j];
ttx=tx+dir[maxdir][0],tty=ty+dir[maxdir][1];
mat[tx][ty]=0;
pos[*j]=make_pair(ttx,tty);
mat[ttx][tty]=*j;
}
if(!cake&&mat[n][m]){
cake=mat[n][m];
b[mat[n][m]]=min(b[mat[n][m]]+(int)(4*mypow[(mat[n][m]+5)/6])/2,(int)(4*mypow[(mat[n][m]+5)/6]));
}
}
double cross_product(int x1,int y1,int x2,int y2){
return x1*y2-x2*y1;
}
bool cross(int i,int tgt,int num){
int x1,y1,x2,y2,x3,y3;
x1=x[i],y1=y[i],x2=pos[tgt].first,y2=pos[tgt].second,x3=pos[num].first,y3=pos[num].second;
int mnx=min(x1,x2),mxx=max(x1,x2),mny=min(y1,y2),mxy=max(y1,y2);
if(x3<mnx||x3>mxx||y3<mny||y3>mxy)
return 0;
if(fabs(cross_product(x1-x3,y1-y3,x2-x3,y2-y3))<=0.5*Get_dist(x1,y1,x2,y2))
return 1;
return 0;
}
void attack(){
int i,tgt,mi,t;
set<int>::iterator j;
for(i=1;i<=s;i++){
if(cake&&Get_sqdist(x[i],y[i],pos[cake].first,pos[cake].second)<=r*r)
tgt=cake;
else{
tgt=0,mi=r*r+1;
for(j=se.begin();j!=se.end();j++)
if((t=Get_sqdist(x[i],y[i],pos[*j].first,pos[*j].second))<mi)
tgt=*j,mi=t;
if(!tgt)
continue;
}
b[tgt]-=d;
for(j=se.begin();j!=se.end();j++)
if(*j!=tgt&&cross(i,tgt,*j))
b[*j]-=d;
}
}
bool beh_attack(){
set<int>::iterator j;
stack<int>ss;
for(j=se.begin();j!=se.end();j++)
if(b[*j]<0){
ss.push(*j);
mat[pos[*j].first][pos[*j].second]=0;
cnt--;
}
while(!ss.empty()){
se.erase(ss.top());
ss.pop();
}
if(cake){
if(b[cake]<0)
cake=0;
else if(!pos[cake].first&&!pos[cake].second)
return 1;
}
return 0;
}
void ending(){
int i,j;
for(i=0;i<=n;i++)
for(j=0;j<=m;j++)
if(f[i][j])
f[i][j]--;
}
bool solve(){
for(tms=1;tms<=t;tms++){
born();
move();
attack();
if(beh_attack())
return 1;
ending();
}
return 0;
}
void print(){
printf("%d\n",cnt);
for(set<int>::iterator j=se.begin();j!=se.end();j++)
printf("%d %d %d %d %d\n",tms-bt[*j],(*j+5)/6,b[*j],pos[*j].first,pos[*j].second);
}
void prepare(){
mypow[0]=1;
for(int i=1;i<=t;i++)
mypow[i]=mypow[i-1]*1.1;
}
int main()
{
read();
prepare();
if(solve())
printf("Game over after %d seconds\n",tms);
else
puts("The game is going on");
print();
}