【kuangbin带你飞】简单搜索 HDU2612——Find a way(双路BFS)

Find a way

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


 

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

 

(截图插件出了点问题,只能直接复制题面了)

    此题的题意是Y和M要在KFC约会,给出一张图,图上可能有很多KFC,要求找到两人去KFC的时间的和的最小值。

    此类在图上找最短距离的题,就可以想到用BFS来做,但由于有两个起点,且最终需要计算两个起点到KFC的距离最小和,那么不论以谁为起点做BFS都是行不通的。这时候就需要使用双路BFS,以Y和M分别作为起点进行BFS。先看代码:

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <string>
#include <stack>
#include <queue>
#include <cmath>
#include <list>
#include <map>
#include <set>

using namespace std;

#define close ios::sync_with_stdio(false);cin.tie(0)
#define test freopen("test_data.txt","r",stdin)
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) (x&-x)
#define INF 0x3f3f3f3f
#define pb push_back

const int movex[] = {-1, 0, 0, 1};
const int movey[] = { 0,-1, 1, 0};

struct node{
	int x;
	int y;
	int step;
	node(int xx, int yy, int stepp){
		x=xx;
		y=yy;
		step=stepp;
	}
};
int n,m,M_x,M_y,Y_x,Y_y,minn;
string mp[205];
int vis[205][205];
int dis_Y[205][205];
int dis_M[205][205];
queue<node>q;

bool Judge(int x, int y){
	return (x<0||y<0||x>=n||y>=m||mp[x][y]=='#'||vis[x][y])?false:true;
}
void Init(){
	minn=INF;
	ms(vis,0);
	ms(dis_Y,0);
	ms(dis_M,0);
	while(!q.empty()) q.pop();
}
void BFS(node a, int dis[][205]){
	node temp=a;
	q.push(temp);
	while(!q.empty()){
		temp=q.front();
		q.pop();
		for(int i=0;i<4;i++){
			int X=temp.x+movex[i];
			int Y=temp.y+movey[i];
			int time=temp.step+1;
			if(!Judge(X,Y)) continue;
			vis[X][Y]=1;
			if(mp[X][Y]=='@') dis[X][Y]=time;
			q.push(node(X,Y,time));
		}
	}
}
int main() {
	close;
	//test;
	while(cin>>n>>m) {
		Init();
		for(int i=0; i<n; i++) {
			cin>>mp[i];
		}
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				if(mp[i][j]=='Y'){
					Y_x=i;
					Y_y=j; 
				}
				if(mp[i][j]=='M'){
					M_x=i;
					M_y=j; 
				}
			}
		}
		vis[Y_x][Y_y]=1;
		BFS(node(Y_x,Y_y,0),dis_Y);
		ms(vis,0);
		vis[M_x][M_y]=1;
		BFS(node(M_x,M_y,0),dis_M);
		for(int i=0;i<n;i++){
			for(int j=0;j<m;j++){
				if(dis_Y[i][j]&&dis_M[i][j]) minn=min(minn,dis_Y[i][j]+dis_M[i][j]);
			}
		}
		cout<<minn*11<<endl;
	}
	return 0;
}

     我们在输入图后,先找出Y和M的起始位置,再分别用dis_Y和dis_M两个二维数组来储存从Y以及M到所有KFC的距离。如何维护dis_Y和dis_M中的数据?用BFS,总体框架是比较正常的BFS思路,在此就不赘述原理了。注意在搜到KFC时,需要将当前步数赋给对应的dis数组中的对应位置,若该位置不是KFC,就置为0(这一步在初始化时已经完成),便于之后的判断。最后遍历一遍,找出最小和就好了。这样一来,双路BFS的思路就很清晰了:

1、开两个dis二维数组,分别存储Y和M到各KFC的距离

2、分别以Y和M为起点进行BFS,维护两个dis数组中的数据

3、遍历两个dis数组,找出最小的和

    这题虽然表面上是双路BFS,但实际上与普通的BFS裸题没有什么区别,思路也不难,只要想到用两个数组来存距离就可以了,认真对待就能顺利解决。我在前几周的集训中看到这题,无意听到别人说是“双路BFS”,顿时感觉这玩意儿好难啊,我必定不会,但几周后再看这题,也不过如此,因此最大的困难 其实还是在于自己。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值