HDU 2612 Find a way(bfs : 两起点到同一终点的最小步数,终点不唯一)

Find a way

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 21520    Accepted Submission(s): 6988


Problem Description
Pass a year learning in Hangzhou, yifenfei arrival hometown Ningbo at finally. Leave Ningbo one year, yifenfei have many people to meet. Especially a good friend Merceki.
Yifenfei’s home is at the countryside, but Merceki’s home is in the center of city. So yifenfei made arrangements with Merceki to meet at a KFC. There are many KFC in Ningbo, they want to choose one that let the total time to it be most smallest. 
Now give you a Ningbo map, Both yifenfei and Merceki can move up, down ,left, right to the adjacent road by cost 11 minutes.
 

Input
The input contains multiple test cases.
Each test case include, first two integers n, m. (2<=n,m<=200). 
Next n lines, each line included m character.
‘Y’ express yifenfei initial position.
‘M’    express Merceki initial position.
‘#’ forbid road;
‘.’ Road.
‘@’ KCF
 

Output
For each test case output the minimum total time that both yifenfei and Merceki to arrival one of KFC.You may sure there is always have a KFC that can let them meet.
 

Sample Input
 
  
4 4
Y.#@
....
.#..
@..M
4 4
Y.#@
....
.#..
@#.M
5 5
Y..@.
.#...
.#...
@..M.
#...#
 

Sample Output
 
  
66
88
66

没想到BFS还能这么玩!!!之前只知道bfs求到终点的最短路,没想到也可以求起点到地图任意点的最短路(打表的感觉),两次bfs,分别求出Y,M到地图任意点的步数,再遍历图中的每一个'@',比较Y,M到每个'@'点的距离和,输出最小值*11。62ms.

我当时就想到了分别以Y,M为起点,每次调用bfs求出到'@'的距离,找出最小值,这里有n个@,就要调用2*n次bfs,提交超时,而第一个方法,总共就调用2次。

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
int f[4][2]={0,1,1,0,-1,0,0,-1};
int n,m;
struct node{
	int x,y;
};
int x1,x2,y1,y2;
char mat[205][205];
int vis[205][205][2];//记录走过(i,j)点没,[2]是两个起点,下同 
int dp[205][205][2];//记录起点到(i,j)的总步数,打表 
int bfs(int a,int b,int c)
{
	queue<node>q;
	node s,t;
	s.x=a;
	s.y=b;
	vis[a][b][c]=1;
	dp[a][b][c]=0;
	q.push(s);
	while(!q.empty())
	{
		t=q.front();
		q.pop();
		for(int i=0;i<4;i++)
		{
			s.x=t.x+f[i][0];
			s.y=t.y+f[i][1];
			if(vis[s.x][s.y][c]||s.x>=n||s.y>=m||s.x<0||s.y<0||mat[s.x][s.y]=='#')
				continue;
			vis[s.x][s.y][c]=1;//经过此点 
			dp[s.x][s.y][c]=dp[t.x][t.y][c]+1;//记录步数 
			q.push(s);
		}
	}
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		memset(vis,0,sizeof(vis));
		getchar();
		int num=0;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{
				scanf("%c",&mat[i][j]);
				if(mat[i][j]=='Y')
				{//Y,M都是起点 
					x1=i;y1=j;
				}
				else if(mat[i][j]=='M')
				{
					x2=i;y2=j;
				}
			}
			getchar();
		}
		bfs(x1,y1,0);//用0,1区分Y,M 
		bfs(x2,y2,1);
		int minn=99999999;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{//(i,j)是'@',并且Y,M都可到达(i,j),计算和的最小值 
				if(mat[i][j]=='@'&&vis[i][j][0]&&vis[i][j][1]&&dp[i][j][0]+dp[i][j][1]<minn)
					minn=dp[i][j][0]+dp[i][j][1];
			}
		}
		printf("%d\n",minn*11);
	}
}

最后附上我的超时代码

#include<stdio.h>
#include<string.h>
#include<queue>
#include<algorithm>
using namespace std;
int f[4][2]={0,1,1,0,-1,0,0,-1};
int n,m;
struct node{
	int x,y;
	int temp;
};
struct point{
	int x,y;
}poi[500];
int x1,x2,y1,y2;
char mat[205][205];
int vis[205][205];
int bfs(int a,int b,point k)
{
	memset(vis,0,sizeof(vis));
	queue<node>q;
	node s,t;
	s.x=a;
	s.y=b;
	s.temp=0;
	vis[a][b]=1;
	q.push(s);
	while(!q.empty())
	{
		t=q.front();
		q.pop();
		if(t.x==k.x&&t.y==k.y)
		{
			return t.temp;
		}
		for(int i=0;i<4;i++)
		{
			s.x=t.x+f[i][0];
			s.y=t.y+f[i][1];
			s.temp=t.temp+1;
			if(vis[s.x][s.y]||s.x>=n||s.y>=m||s.x<0||s.y<0||mat[s.x][s.y]=='#')
				continue;
			vis[s.x][s.y]=1;
			q.push(s); 
		}
	}
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		getchar();
		int num=0;
		for(int i=0;i<n;i++)
		{
			for(int j=0;j<m;j++)
			{
				scanf("%c",&mat[i][j]);
				if(mat[i][j]=='Y')
				{
					x1=i;y1=j;
				}
				else if(mat[i][j]=='M')
				{
					x2=i;y2=j;
				}
				else if(mat[i][j]=='@')
				{
					poi[num].x=i;
					poi[num++].y=j;
				}
			}
			getchar();
		}
		int minn=99999999;
		int sum;
		for(int i=0;i<num;i++)
		{
			sum=bfs(x1,y1,poi[i])+bfs(x2,y2,poi[i]);
			if(sum<minn)
				minn=sum;
		}
		printf("%d\n",minn*11);
	}
}

猜你喜欢

转载自blog.csdn.net/BBHHTT/article/details/80230863