uva Fire! BFS

题目链接
https://vjudge.net/contest/353188#problem/K

大体题意就是在火烧到自己之前逃离迷宫,#代表墙,.代表可以走的路,J代表人的起点,F代表火的起点。
具体可以参照样例
1 //样例个数
4 4
.###
#JF#
#…#
#…#

题意比较明了,可以让火bfs一遍,记录能到的每一个点的时间。
但是这个题简直就是英语渣渣的噩梦,在oj上WA了无数次也没找到错在了哪里,去网上查了查,看到题解的第一句话我就懂了,原来火有多个起点,也就是F不一定只有一个,可能有多个F,它题目中火那个单词加了s,(我连那个是火的单词都不知道,233333).既然有多个起点,那么可能有多个火到达同一个点 ,如果对于每一个F都bfs一遍取每一个点的最小值的话,会超时,而加了优化就有可能WA掉(亲身经历),那么干脆直接把这些点一起放到队列里面,这样就可以完美的解决了.

#include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
 
const int N=1010;

int t,n,m,x1,y1,x2,y2;
int dir[4][2]={1,0,-1,0,0,1,0,-1};
int pis[N][N];
char str[N][N];
bool st[N][N];

struct Node
{
	int x,y,step;
};

queue<Node>p;//定义全局的队列,共用一个st

int bfs1(int x,int y)
{
	memset(st,false,sizeof st);
	
	queue<Node>q;
	Node fis;
	fis.x=x,fis.y=y,fis.step=0;
	st[x][y]=true;
	q.push(fis);
	
	while(q.size())
	{
		Node cur=q.front();
		q.pop();
		
		if(cur.x==1||cur.x==n||cur.y==1||cur.y==m)
			return cur.step;
		
		Node next;
		next.step=cur.step+1;
		for(int i=0;i<4;i++)
		{
			int xx=next.x=cur.x+dir[i][0];
			int yy=next.y=cur.y+dir[i][1];
			if(xx<1||xx>n||yy<1||yy>m||st[xx][yy]||str[xx][yy]=='#')
				continue;
			
			if(pis[xx][yy]<=next.step)//判断是否能在火到之前到达这个点
				continue;
				
			st[xx][yy]=true;
			q.push(next);
		}
	}
	return -1;
}

void bfs2()
{
	
	while(p.size())
	{
		Node cur=p.front();
		p.pop();
		
		pis[cur.x][cur.y]=cur.step;
		
		Node next;
		next.step=cur.step+1;
		
		for(int i=0;i<4;i++)
		{
			int xx=next.x=cur.x+dir[i][0];
			int yy=next.y=cur.y+dir[i][1];
			if(xx<1||xx>n||yy<1||yy>m||st[xx][yy]||str[xx][yy]=='#')
				continue;
				
			st[xx][yy]=true;
			p.push(next);
		}
	}
	
}

int main()
{
	cin>>t;
	
	while(t--)
	{
		memset(pis,0x3f,sizeof pis);//初始化距离为正无穷
		memset(st,false,sizeof st);
		
		cin>>n>>m;
		
		for(int i=1;i<=n;i++)
		{
			scanf("%s",str[i]+1);
			for(int j=1;j<=m;j++)
				if(str[i][j]=='J')
					x1=i,y1=j;
				else if(str[i][j]=='F')
				{
					p.push({i,j,0});//入队
					st[i][j]=true;
				}
		}
		
		bfs2();
		
		int res=bfs1(x1,y1);
		
		if(res==-1) 
			printf("IMPOSSIBLE\n");
		else 
			printf("%d\n",res+1);//看样例可以知道出去还需要一步
	}
	
	
	return 0;
}
发布了43 篇原创文章 · 获赞 1 · 访问量 1588

猜你喜欢

转载自blog.csdn.net/DaNIelLAk/article/details/104148837