您的位置:首页 > 其它

【BZOJ1033】[ZJOI2008]杀蚂蚁antbuster【模拟】

2017-01-16 13:25 399 查看
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#define FOREACH if(cnt)for(int i=hed;i;i=ants[i].nxt)
using namespace std;

const int MX=250,MXT=200050,inf=0x3f3f3f3f;

const int dx[5]={0,0,1,0,-1},dy[5]={0,1,0,-1,0};
int mxhp[MX];
int n,m,s,d,r,t;
int x[MX],y[MX];
int f[MX][MX];
bool ava[MX][MX];
int hed,tai,antc,cnt,cur,target;
struct ant* ants;
struct ant{
int x,y,lstx,lsty,hp,lvl,pre,nxt,bornt;
inline void creat()
{
ant res;
res.lstx=res.lsty=-1;
res.lvl=antc/6+1;
res.bornt=cur;
res.hp=mxhp[res.lvl];
res.x=res.y=0;
res.pre=tai;res.nxt=0;
ants[++antc]=res;
ants[tai].nxt=antc;
tai=antc;
if(!cnt)hed=antc;
cnt++;
ava[0][0]=false;
}
inline void addf()
{
f[x][y]+=((target==this-ants)?5:2);
}
inline bool ck()
{
return (!x&&!y&&(target==this-ants));
}
inline bool ckdead()
{
if(hp<0)
{
if(target==this-ants)target=0;
cnt--;
if(hed==this-ants)hed=nxt;else ants[pre].nxt=nxt;
if(tai==this-ants){tai=pre;ants[tai].nxt=0;}else ants[nxt].pre=pre;
ava[x][y]=true;
}
return hp<0;
}
inline void getck()
{
if(!target&&x==n&&y==m)
{
target=this-ants;
hp=min(hp+(mxhp[lvl]>>1),mxhp[lvl]);
}
}
inline void mov()
{
int chose=0,mxf=-1;
int xx,yy;
for(int i=1;i<=4;i++)
{
xx=x+dx[i],yy=y+dy[i];
if(!(xx==lstx&&yy==lsty)&&xx>=0&&yy>=0&&xx<=n&&yy<=m&&ava[xx][yy]&&f[xx][yy]>mxf)
{
chose=i;
mxf=f[xx][yy];
}
}
if(chose&&(cur-bornt+1)%5==0)
{
for(int i=3;i>=0;i--)
{
int tmp=(chose+i-1)%4+1;
xx=x+dx[tmp],yy=y+dy[tmp];
if(!(xx==lstx&&yy==lsty)&&xx>=0&&yy>=0&&xx<=n&&yy<=m&&ava[xx][yy])
{
chose=tmp;break;
}
}
}
lstx=x,lsty=y;
if(chose)
{
xx=x+dx[chose],yy=y+dy[chose];
ava[x][y]=true;
x=xx,y=yy;
ava[x][y]=false;
}
}
}pool[MXT],null;

void rd()
{
scanf("%d%d%d%d%d",&n,&m,&s,&d,&r);
for(int i=1;i<=s;i++)scanf("%d%d",&x[i],&y[i]);
scanf("%d",&t);
}
void ini()
{
ants=pool;
for(int i=1;i<=200;i++)
{
mxhp[i]=floor(4.0*pow(1.1,(double)i));
}
memset(ava,true,sizeof(ava));
for(int i=1;i<=s;i++)ava[x[i]][y[i]]=false;
}
#define DIS(i) ((x[j]-ants[i].x)*(x[j]-ants[i].x)+(y[j]-ants[i].y)*(y[j]-ants[i].y))
#define S (abs(xx*y[j]+ty*x[j]+tx*yy-yy*x[j]-xx*ty-tx*y[j]))
void atk()
{
for(int j=1;j<=s;j++)
{
int tg=0;
if(target&&DIS(target)<=r*r)tg=target;
if(!tg)
{
int mndis=inf;
FOREACH{
int dis=DIS(i);
if(dis<mndis&&dis<=r*r){
mndis=dis;tg=i;
}
}
}
if(tg)
{
int tx=ants[tg].x,ty=ants[tg].y;
int dis3=DIS(tg);
FOREACH{
int xx=ants[i].x,yy=ants[i].y;
int dis1=(xx-tx)*(xx-tx)+(yy-ty)*(yy-ty),dis2=DIS(i);
if(dis1+dis3>=dis2&&dis3+dis2>=dis1&&(4*S*S)<=dis3)
ants[i].hp-=d;
}
}
}
}
bool wk()
{
for(cur=1;cur<=t;cur++)
{
if(cnt<6&&ava[0][0])null.creat();
FOREACH{ants[i].addf();}
FOREACH{ants[i].mov();}
FOREACH{ants[i].getck();}
atk();
FOREACH{ants[i].ckdead();}
FOREACH{
if(ants[i].ck()){return false;}
}
for(int i=0;i<=n;i++)for(int j=0;j<=m;j++)f[i][j]=max(f[i][j]-1,0);
}
cur--;
return true;
}
int main()
{
rd();
ini();
bool aliv = wk();
if(!aliv)printf("Game over after %d seconds\n",cur);
else printf("The game is going on\n");
printf("%d\n",cnt);
FOREACH{printf("%d %d %d %d %d\n",cur-ants[i].bornt+(aliv?1:0),ants[i].lvl,ants[i].hp,ants[i].x,ants[i].y);}
return 0;
}

注意事项:

1 蚂蚁有大小,并且直径是1(不是半径)

2 蚂蚁是先计算全部信息素,再全部移动,后面的蚂蚁留下信息素在前面的蚂蚁移动之前

3 age可以不存,链式存储就好了

4 直接维护信息素的值就好了

5 分清计算的乘号和加号(坑了1个小时qaq

6 炮塔是一起攻击的,所以就算某只蚂蚁的血被打成了负,还是要被攻击。

7 封装大法好

8 最好不要double,通分一下用int就好了

参考:
http://blog.csdn.net/braketbn/article/details/50813144
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  模拟