• [ZJOI2008]杀蚂蚁antbuster 题解


    一个题目的可读版本:https://www.zybuluo.com/Jerusalem/note/221811







     这两天做的又一道大模拟题,感觉这玩意有毒,会上瘾啊……

     比起猪国杀这道题真心不知道高到哪里去了,当然,我只是说题目。具体难度说句实在地,真觉得比猪国杀要容易一些。

     先说一下时间线:

        第一天下午:打完猪国杀,立志杀蚂蚁。

        第二天下午:3:00 开搞,读题,扫雷。

              3:30 正式打码。

              5:20 代码完成,开始调试。

              6:00 解决肚子问题

              6:25 回来继续搞

              6:31 AC!!

     比起猪国杀那长征般的的历程,不得不去说杀蚂蚁要简单太多太多了。至少从代码长度就可以看出来。

     先说一些坑点:

         1.刚出生的蚂蚁年龄是0。

         2.行动方式变化的蚂蚁(年龄+1)%5==0而不是年龄%5=0。

         3.对于一些较复杂的求蚂蚁与塔之间的连线的解析式的方法可能会被卡精度,再次感谢原子核教我的解方程式打法避免被卡精度。

         4.大视野上的注释有误。

         5.蚂蚁死了之后他原来位置上记得标记为无蚂蚁。

     还是那句话,比猪国杀强多了。

      然后,我们只要按照题目中给出的“一秒钟发生的事”的顺序打出对应函数就好了,毕竟只是模拟题,只要不太浪,单纯的模拟是不会T掉的。

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <algorithm>
    #include <cmath>
    #define N 200004
    using namespace std;
    int n,m,s,d,r,t,js,zz,target,zy[5][2];
    struct tow
    {
    	int x,y;
    }tower[50];
    struct an
    {
    	int age,level,hp,x,y,lx,ly,id;
    }ant[N];
    struct ma
    {
    	bool tower,ant;
    	int inf;
    }map[10][10];
    int pre[N],fro[N];
    void print(int x)
    {
    	printf("%d %d %d %d %d
    ",ant[x].age,ant[x].level,ant[x].hp,ant[x].x,ant[x].y);
    }
    void born() 
    {
    	if(js<6&&!map[0][0].ant)
    	{
    		js++;
    		zz++;
    		ant[zz].age=0; ant[zz].id=zz;
    		ant[zz].level=(zz-1)/6+1;
    		ant[zz].hp=4*pow(1.1,ant[zz].level);
    		map[0][0].ant=1;
    		ant[zz].x=ant[zz].y=0;
    		pre[zz]=pre[0]; fro[zz]=0;
    		fro[pre[0]]=zz; pre[0]=zz;
    	}
    }
    void stay_information()
    {
    	int now=fro[0];
    	while(now)
    	{
    		map[ant[now].x][ant[now].y].inf+=2;
    		if(target==now)map[ant[now].x][ant[now].y].inf+=3;
    		now=fro[now];
    	}
    }
    bool check(int x,int y)
    {
    	if(map[x][y].tower||map[x][y].ant)return 0;
    	if(x<0||y<0)return 0;
    	if(x>n||y>m)return 0;
    	return 1;
    }
    void move_an_ant(int aa)
    {
    	int x=ant[aa].x,y=ant[aa].y;
    	bool yx=1;
    	int mx=-1,to=0;
    	for(int i=1;i<=4;i++)
    	{
    		int tx=x+zy[i][0],ty=y+zy[i][1];
    		if(!check(tx,ty)||(tx==ant[aa].lx&&ant[aa].ly==ty))continue;
    		if(mx<map[tx][ty].inf)
    		{
    			to=i;
    			mx=map[tx][ty].inf;
    		}
    	}
    	if((ant[aa].age+1)%5==0)
    	{
    		int la=to;
    		for(int i=to-1;i>0;i--)
    		{
    			int tx=x+zy[i][0],ty=y+zy[i][1];
    			if(!check(tx,ty)||(tx==ant[aa].lx&&ant[aa].ly==ty))continue;
    			to=i;
    			break;
    		}
    		if(to==la)
    		{
    			for(int i=4;i>=to;i--)
    			{
    				int tx=x+zy[i][0],ty=y+zy[i][1];
    				if(!check(tx,ty)||(tx==ant[aa].lx&&ant[aa].ly==ty))continue;
    				to=i;
    				break;
    			}
    		}
    	}
    	map[x][y].ant=0;
    	ant[aa].lx=ant[aa].x,ant[aa].ly=ant[aa].y;
    	ant[aa].x+=zy[to][0],ant[aa].y+=zy[to][1];
    	if(ant[aa].x==n&&ant[aa].y==m&&!target)
    	{
    		target=aa;
    		ant[aa].hp=min(ant[aa].hp+2*pow(1.1,ant[aa].level),4*pow(1.1,ant[aa].level));
    	}
    	map[ant[aa].x][ant[aa].y].ant=1;
    }
    void move_ants()
    {
    	int now=fro[0];
    	while(now)
    	{
    		move_an_ant(now);
    		now=fro[now];
    	}
    }
    int if_attack(int aa,int bb)
    {
    	int a=tower[aa].x-ant[bb].x,b=tower[aa].y-ant[bb].y;
    	a*=a,b*=b;
    	if(a+b>r*r)return 0;
    	return a+b;
    }
    void attack_ants()
    {
    	for(int i=1;i<=s;i++)
    	{
    		int now=fro[0],to=0,mn=0x7fffffff;
    		while(now)
    		{	
    			int tt=if_attack(i,now);
    			if(tt)
    			{
    				if(tt<mn) mn=tt,to=now;
    				if(target==now)
    				{
    					to=now;
    					break;
    				}
    			}
    			now=fro[now];
    		}
    		if(!to)continue;
    		int mx=max(tower[i].x,ant[to].x),my=max(tower[i].y,ant[to].y);
    		int nx=min(tower[i].x,ant[to].x),ny=min(tower[i].y,ant[to].y);
    		now=fro[0];
    		int A=tower[i].y-ant[to].y,B=ant[to].x-tower[i].x;
    		int C=tower[i].x*ant[to].y-tower[i].y*ant[to].x;
    		double fm=1.0/sqrt(A*A+B*B);
    		while(now)
    		{
    			if(ant[now].x>mx||ant[now].x<nx)
    			{
    				now=fro[now];
    				continue;
    			}
    			if(ant[now].y>my||ant[now].y<ny)
    			{
    				now=fro[now];
    				continue;
    			}
    			if(fabs(ant[now].x*A+ant[now].y*B+C)*fm<=0.50) ant[now].hp-=d;
    			now=fro[now];
    		}
    	}
    }
    void find_death()
    {
    	int now=fro[0];
    	while(now)
    	{
    		if(ant[now].hp<0)
    		{
    			js--;
    			fro[pre[now]]=fro[now];
    			pre[fro[now]]=pre[now];
    			map[ant[now].x][ant[now].y].ant=0;
    			if(now==target)target=0;
    		}
    		now=fro[now];
    	}
    }
    void come_to_end(bool human,int ti)
    {
    	if(human) printf("The game is going on
    ");
    	else printf("Game over after %d seconds
    ",ti);
    	int now=fro[0];
    	printf("%d
    ",js);
    	while(now)
    	{
    		print(now);
    		now=fro[now];
    	}
    }
    void clean_map()
    {
    	for(int i=0;i<=n;i++)
    	{
    		for(int j=0;j<=m;j++)
    		{
    			if(!map[i][j].inf)continue;
    			map[i][j].inf--;
    		}
    	}
    	int now=fro[0];
    	while(now)
    	{
    		ant[now].age++;
    		now=fro[now];
    	}
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	scanf("%d%d%d",&s,&d,&r);
    	for(int i=1;i<=s;i++)
    	{
    		scanf("%d%d",&tower[i].x,&tower[i].y);
    		map[tower[i].x][tower[i].y].tower=1;
    	}
    	scanf("%d",&t);
    	zy[1][0]=0,zy[1][1]=1;
    	zy[2][0]=1,zy[2][1]=0;
    	zy[3][0]=0,zy[3][1]=-1;
    	zy[4][0]=-1,zy[4][1]=0;
    	for(int i=1;i<=t;i++)
    	{
    		born();
    		stay_information();
    		move_ants();
    		attack_ants();
    		find_death();
    		if(target&&(!ant[target].x)&&(!ant[target].y))
    		{
    			come_to_end(0,i);
    			exit(0);
    		}
    		clean_map();
    	}
    	come_to_end(1,0);
    	return 0;
    }
    

      

  • 相关阅读:
    shared_ptr weak_ptr boost 内存管理
    _vimrc win7 gvim
    qt 拖放
    数学小魔术 斐波那契数列
    qt4 程序 移植到 qt5
    (转)字符串匹配算法总结
    c++11
    BM 字符串匹配
    编译qt5 demo
    c++ 类库 学习资源
  • 原文地址:https://www.cnblogs.com/liutianrui/p/7652591.html
Copyright © 2020-2023  润新知