POJ 3170 Knights of Ni(bfs)

Description

Bessie is in Camelot and has encountered a sticky situation: she needs to pass through the forest that is guarded by the Knights of Ni. In order to pass through safely, the Knights have demanded that she bring them a single shrubbery. Time is of the essence, and Bessie must find and bring them a shrubbery as quickly as possible.

Bessie has a map of of the forest, which is partitioned into a square grid arrayed in the usual manner, with axes parallel to the X and Y axes. The map is W x H units in size (1 <= W <= 1000; 1 <= H <= 1000).

The map shows where Bessie starts her quest, the single square where the Knights of Ni are, and the locations of all the shrubberies of the land. It also shows which areas of the map can be traverse (some grid blocks are impassable because of swamps, cliffs, and killer rabbits). Bessie can not pass through the Knights of Ni square without a shrubbery.

In order to make sure that she follows the map correctly, Bessie can only move in four directions: North, East, South, or West (i.e., NOT diagonally). She requires one day to complete a traversal from one grid block to a neighboring grid block.

It is guaranteed that Bessie will be able to obtain a shrubbery and then deliver it to the Knights of Ni. Determine the quickest way for her to do so.

Input

Line 1: Two space-separated integers: W and H.

Lines 2…?: These lines describe the map, row by row. The first line describes the most northwest part of the map; the last line describes the most southeast part of the map. Successive integers in the input describe columns of the map from west to east. Each new row of a map’s description starts on a new input line, and each input line contains no more than 40 space-separated integers. If W <= 40, then each input line describes a complete row of the map. If W > 40, then more than one line is used to describe a single row, 40 integers on each line except potentially the last one. No input line ever describes elements of more than one row.

The integers that describe the map come from this set:
0: Square through which Bessie can travel
1: Impassable square that Bessie cannot traverse
2: Bessie’s starting location
3: Location of the Knights of Ni
4: Location of a shrubbery

Output

Line 1: D, the minimum number of days it will take Bessie to reach a shrubbery and bring it to the Knights of Ni.

Sample Input

8 4
4 1 0 0 0 0 1 0
0 0 0 1 0 1 0 0
0 2 1 1 3 0 4 0
0 0 0 4 1 1 1 0

Sample Output

11

思路

首先,要找最小时间,肯定是用bfs搜索,bfs向四周搜索是同时进行的,有结果就返回,可以保证时间最小,dfs一次搜索所有连通的,不太容易比较时间。这题我做了好久一直没过。刚开始是从起点直接搜索终点,路过灌木做标记,只有标记过了,到终点才终止,但是MLE。后来分别以每个灌木为起点bfs起点和终点,取二者相加的最小值,TLE。然后,分别从起点和终点开始搜索灌木,但是是遍历整个图,没有退出,这样就可以记录到了每一个灌木的时间,最后二者相加取最小。细节见注释

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

const int xx[]={
    
    0,0,1,-1};					//方向 
const int yy[]={
    
    1,-1,0,0};
struct state
{
    
    
	int x,y,t;								//位置 时间 
};
queue<state> q;
int map[1005][1005];
int t[1005][1005][2];						//分别记录起点和终点到灌木的时间 
int vis[1005][1005];						//标记走过的位置  因为要最小的时间,走过的顺序是按照时间的,后面的时间肯定比前面大且没有其他条件影响 
int x0,y0,w,h,x,y;							//起点 终点 

inline int read()							//快读 
{
    
    
   int s=0,w=1;
   char ch=getchar();
   while(ch<'0'||ch>'9'){
    
    if(ch=='-')w=-1;ch=getchar();}
   while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
   return s*w;
}

void bfs(int sx,int sy,int p)				//起点位置  p是记录此次bfs的是起点还是终点 
{
    
    
	while(q.size())
		q.pop();
	state tmp;
	tmp.x=sx;
	tmp.y=sy;
	tmp.t=0;								//起点 
	q.push(tmp);
	while(q.size())
	{
    
    
		tmp=q.front();
		q.pop();
		for(int i=0;i<4;i++)				//向四周走 
		{
    
    
			int dx=tmp.x+xx[i],dy=tmp.y+yy[i];
			if(dx>h||dy>w||dx<1||dy<1||vis[dx][dy]||map[dx][dy]==1)
				continue;					//条件判断 超界 走过 死路 
			vis[dx][dy]=1;					//标记 
			state st;
			st.x=dx;
			st.y=dy;
			st.t=tmp.t+1;
			if(map[dx][dy]==4)
				t[dx][dy][p]=st.t;			//灌木丛记录时间 
			q.push(st);						//加入队列,搜索其四周 
		}
	}
}

int main()
{
    
    
	cin>>w>>h;
	queue<state>bush;
	for(int i=1;i<=h;i++)
		for(int j=1;j<=w;j++)
		{
    
    
			map[i][j]=read();
			if(map[i][j]==2)
			{
    
    
				x0=i;
				y0=j;
			}
			if(map[i][j]==3)
			{
    
    
				x=i;
				y=j;
			}
		}
	int ans=1e8;
	bfs(x0,y0,0);							//从起点bfs灌木 
	memset(vis,0,sizeof(vis));				//标记清零 
	bfs(x,y,1);								//从终点bfs灌木 
	for(int i=1;i<=h;i++)
		for(int j=1;j<=w;j++)
			if(map[i][j]==4&&t[i][j][0]&&t[i][j][1])	//注意!!!可能有的灌木无法到达 
				ans=min(t[i][j][0]+t[i][j][1],ans);
	cout<<ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_54621932/article/details/113959415
今日推荐