HDU3533Escape(BFS+预处理)

题目在这:传送门
分析:A要从(0,0)跑到(m,n)处,地图各个地方有炮台会发射子弹,A必须要不中弹而且能量用完之前到达(m,n),可以的话输出需要的时间,不行就输出Bad luck!
思路:求最短路径用BFS,而这题情况条件比较多,先要多子弹可能会出现的位置和时间做一个预处理,就先标记好,在BFS的时候绕开子弹
AC代码:

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<cmath>
using namespace std;
bool bu[1000][105][105];		//记录子弹出现情况
bool g[105][105];		//记录碉堡位置
int m,n,k,d;
bool vis[1000][105][105];			//标记该点某时刻是否走过
int dir[][2]= {{1,0},{-1,0},{0,1},{0,-1},{0,0}};
struct castle {
	char c;
	int t;
	int v;
	int x,y;
	castle(int t=0,int v=0,int x=0,int y=0,char c='N'):t(t),v(v),x(x),y(y),c(c) {}
} cas[105];

struct node {		//用一个结构表示某时刻某点
	int x,y;			
	int time;			//跑到此点时候所需要的时间
	node(int x=0,int y=0,int time=0):x(x),y(y),time(time) {}
};

void pre() {		//预处理
	memset(bu,false,sizeof(bu));
	for(int i=0; i<k; i++) {
		int dx=0,dy=0;
		switch(cas[i].c) {
			case 'N':	dx=-1;  	break;
			case 'S':	dx=1;		break;
			case 'W':  dy=-1;   	break;
			case 'E':	dy=1;    	break;
		}
		int nx,ny;
		for(int j=1;; j++) {			//走到每一步子弹的情况
			nx=j*dx+cas[i].x;
			ny=j*dy+cas[i].y;
			if(nx<0||nx>m||ny<0||ny>n)	break;
			if(g[nx][ny])	break;		//遇到其他堡垒停下来
			if(j%cas[i].v==0) {			//记录子弹可能存在的位置
				for(int h=j/cas[i].v; h<=d; h+=cas[i].t)
					bu[h][nx][ny]=true;
			}
		}
	}
}
bool judge(node &nd) {			//一个剪枝,判断到达某点时能量与还需要走的最短距离的关系
	if(nd.time>d)	return false;
	int temp=abs(nd.x-m)+abs(nd.y-n);
	return d-nd.time>=temp;
}
void bfs() {
	memset(vis,false,sizeof(vis));
	queue<node>que;
	que.push(node(0,0,0));
	vis[0][0][0]=true;
	while(!que.empty()) {
		node p=que.front();
		que.pop();
		if(p.x==m&&p.y==n) {
			printf("%d\n",p.time);
			return;
		}
		for(int i=0; i<5; i++) {
			node next=node(p.x+dir[i][0],p.y+dir[i][1],p.time+1);
			if(!bu[next.time][next.x][next.y]&&next.x>=0&&next.x<=m&&next.y>=0&&next.y<=n&&!g[next.x][next.y]&&judge(next)&&vis[next.time][next.x][next.y]==0) {		
				que.push(next);					//判断某点是否越界,是否有子弹,是否为堡垒,是否走过
				vis[next.time][next.x][next.y]=true;
			}
		}
	}
	printf("Bad luck!\n");
}
int main() {
	while(scanf("%d%d%d%d",&m,&n,&k,&d)==4) {
		getchar();
		memset(g,false,sizeof(g));
		for(int i=0; i<k; i++) {
			scanf("%c",&cas[i].c);
			scanf("%d%d%d%d",&cas[i].t,&cas[i].v,&cas[i].x,&cas[i].y);
			getchar();
			g[cas[i].x][cas[i].y]=true;
		}
		pre();
		bfs();
	}
}

小结:一开始数组开太大,超内存,后来开小了还是超出内存,就把一开始用来标记的Int数组全都换成了bool数组,结果就不超时了。。。我也不知道为啥

猜你喜欢

转载自blog.csdn.net/weixin_43556295/article/details/86684883
今日推荐