[ZJOI2008] 杀蚂蚁(BZOJ上未过)

       dark模拟题。

       计算几何一片空白判线段和圆是否相交来来回回改了五六次,代码也写得很长(还有一部分原因是码风问题233)

       提交记录非常鬼畜:先在Codevs上WA40,把inline全部去掉就AC了;再到洛谷上还是WA40,把O2关掉变成80,数组开大点就AC了。但是BZOJ上还是WA。

       如果哪位大佬帮我看出哪里有点问题(也有可能是比较危险的未定义行为)或者有叉掉我的数据麻烦指出一下,非常感激。

#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<time.h>
#include<vector>
#include<cstring>
#include<stdlib.h>
#include<iostream>
#include<algorithm>
#define LL long long
#define int long long
using namespace std;
const int N=2e5+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const int u[4]={0,1,0,-1};
const int v[4]={1,0,-1,0};

namespace FastIO {
	template<typename tp> void read(tp &x) {
		x=0; register char c=getchar(); register bool f=0;
		for(;c<'0'||c>'9';f|=(c=='-'),c = getchar());
		for(;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-'0',c = getchar());
		if(f) x=-x;
	}
	template<typename tp> void write(tp x) {
		if (x==0) return (void) (putchar('0'));
   	if (x<0) putchar('-'),x=-x;
   	int pr[20]; register int cnt=0;
   	for (;x;x/=10) pr[++cnt]=x%10;
   	while (cnt) putchar(pr[cnt--]+'0');
	}
	template<typename tp> void writeln(tp x) {
		write(x);
		putchar('\n');
	}
}
using namespace FastIO;

int n,m,T,s,d,r,t,Game_end;
int AntIn[15][15],HP_Level[N];

struct Point {
	int InMap,num;
}Map[15][15];

namespace Information_Ant {
	int ord,Num_Ant,target;
	struct Ant {
		int x,y,lasx,lasy;
		int HP,time,cake,level,blood;
	}ant[10],move[10];
	
	void Ant_Born() {
		if (Num_Ant>=6||AntIn[1][1]) return;
		ord++; Num_Ant++; int lev=(ord-1)/6+1,HP=HP_Level[lev];
		ant[Num_Ant]=(Ant) {1,1,0,0,HP,0,0,lev,HP};
		AntIn[1][1]=1;
	}
	
	void Ant_Put() {
		for (int i=1;i<=Num_Ant;i++) {
			int x=ant[i].x,y=ant[i].y;
			Map[x][y].num+=(i==target)?5:2;
		}
	}
	
	int Can_Go(int x,int y) {
		if (!Map[x][y].InMap) return 0;
		if (AntIn[x][y]) return 0;
		return 1;
	}
	
	int Pre(int x) {
		return (!x)?3:x-1;
	}
	
	void Ant_Move(int p) {
		int x=ant[p].x,y=ant[p].y,lasx=ant[p].lasx,lasy=ant[p].lasy;
		int to=-1,maxn=-inf,tot=0;
		for (int i=0;i<4;i++) {
			if (x+u[i]==lasx&&y+v[i]==lasy) continue;
			if (Can_Go(x+u[i],y+v[i])) {
				if (maxn<Map[x+u[i]][y+v[i]].num) maxn=Map[x+u[i]][y+v[i]].num,tot=1,to=i;
				else if (maxn==Map[x+u[i]][y+v[i]].num) tot++;
			}
		}
		if (~to&&tot>1) {
			for (int i=0;i<4;i++) {
				if (x+u[i]==lasx&&y+v[i]==lasy) continue;
				if (Can_Go(x+u[i],y+v[i])&&Map[x+u[i]][y+v[i]].num==maxn) {
					to=i;
					break;
				}
			}
		}
		if (~to&&ant[p].time%5==4) {
			for (int i=Pre(to);i!=to;i=Pre(i)) {
				if (x+u[i]==lasx&&y+v[i]==lasy) continue;
				if (Can_Go(x+u[i],y+v[i])) {
					to=i;
					break;
				}
			}
		}
		ant[p].lasx=x; ant[p].lasy=y;
		if (~to) {
			AntIn[x][y]=0;
			x+=u[to]; y+=v[to];
			AntIn[x][y]=1;
			ant[p].x=x; ant[p].y=y;
		}
		if (target==-1&&x==n&&y==m) {
			target=p;
			ant[p].cake=1;
			ant[p].HP=min(ant[p].blood,ant[p].HP+ant[p].blood/2);
		}
	}
	
	void Ant_Die() {
		int alive=0;
		for (int i=1;i<=Num_Ant;i++) {
			if (ant[i].HP>=0) move[++alive]=ant[i];
			else AntIn[ant[i].x][ant[i].y]=0;
		}	
		for (int i=1;i<=alive;i++)
			ant[i]=move[i];
		Num_Ant=alive; target=-1;
		for (int i=1;i<=alive;i++)
			if (ant[i].cake) target=i;
	}
	
};
using namespace Information_Ant;

namespace Information_Tower {	
	struct Vector {
		int x,y;	
		int Dot(Vector &b) {
			return x*b.x+y*b.y;
		}
	}tower[200];
	
	int Dis(int p,int q) {
		int x=abs(tower[p].x-ant[q].x);
		int y=abs(tower[p].y-ant[q].y);
		return x*x+y*y;
	}
	
	int Can_Attack(int p,int goal) {
		return Dis(p,goal)<=r*r;
	}
	
	int Check_Ver(int u,int v,int w) {
		Vector a=(Vector) {tower[u].x-ant[v].x,tower[u].y-ant[v].y};
		Vector b=(Vector) {ant[w].x-ant[v].x,ant[w].y-ant[v].y};
		return a.Dot(b)>=0;
	}
	
	int Attacked(int p,int q,int goal) {
		if (q==goal) return 1;
		tower[0]=(Vector) {ant[goal].x,ant[goal].y};
		ant[0].x=tower[p].x; ant[0].y=tower[p].y;
		if (Check_Ver(p,goal,q)&&Check_Ver(0,0,q)) {
			int x1=ant[q].x-tower[p].x,y1=ant[q].y-tower[p].y;
			int x2=ant[goal].x-tower[p].x,y2=ant[goal].y-tower[p].y;
			int dx=(x1*y2-x2*y1)*(x1*y2-x2*y1);
			int dy=(x2*x2+y2*y2)/4;
			return dx<=dy;
		}
	}
	
	void Tower_Attack(int p) {
		if (~target&&Can_Attack(p,target)) {
			for (int i=1;i<=Num_Ant;i++)
				if (Attacked(p,i,target)) ant[i].HP-=d;
			return;
		}
		int minv=inf,goal=-1;
		for (int i=1;i<=Num_Ant;i++) {
			int dx=Dis(p,i);
			if (dx<=r*r&&dx<minv) minv=dx,goal=i;
		}
		if (~goal)
			for (int i=1;i<=Num_Ant;i++) {
				if (Attacked(p,i,goal)) ant[i].HP-=d;
			}
	}
	
}
using namespace Information_Tower;

void Init() {
	read(n); read(m); n++; m++;
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
			Map[i][j].InMap=1;
	read(s); read(d); read(r);	
	for (int i=1;i<=s;i++) {
		int x,y;
		read(x); read(y); x++; y++;
		tower[i].x=x; tower[i].y=y;
		Map[x][y].InMap=0;
	}
	read(T); target=-1;
}

int Check_Over() {
	if (target==-1) return 0;
	return ant[target].x==1&&ant[target].y==1;
}

void Second_End() {
	for (int i=1;i<=n;i++)
		for (int j=1;j<=m;j++)
			if (Map[i][j].num) Map[i][j].num--;
	for (int i=1;i<=Num_Ant;i++) ant[i].time++;
}

int Game(int T) {
	Ant_Born();
	Ant_Put();
	for (int i=1;i<=Num_Ant;i++) Ant_Move(i);
	for (int i=1;i<=s;i++) 
		Tower_Attack(i);
	Ant_Die();
	if (Check_Over()) return 0;
	Second_End();
	return 1;
}

void Output() {
	writeln(Num_Ant);
	for (int i=1;i<=Num_Ant;i++) {
		printf("%lld %lld %lld %lld %lld\n",ant[i].time,ant[i].level,ant[i].HP,ant[i].x-1,ant[i].y-1);
	}
}

signed main() {
	Init();
	double x=1;
	for (int i=1;i<=200000;i++) {
		x*=1.1;
		HP_Level[i]=4*x;
	}
	for (t=1;t<=T;t++) {
		if (!Game(t)) {
			Game_end=1;
			printf("Game over after %lld seconds\n",t);
			break;
		}
	}
	if (!Game_end) printf("The game is going on\n");
	Output();
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值