HDU 2612 Find a way 多起点 多终点 BFS

本文介绍了如何使用BFS算法解决多起点多终点的最短路径问题,通过预处理得到从任意起点到达任意点的最短路径,并用于找到两个特定点之间的最短总路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

N - Find a way
Time Limit:1000MS    Memory Limit:32768KB    64bit IO Format:%I64d & %I64u

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之后,就得到了起点到达任何一点的最短路径长度,比较起来,前一种方法使代码更加整洁,后一种则通用性更强,可以各取所爱,但是最好不要两种同时出现,除非你想TLE 20次。。。大哭


#include <iostream>
#include <cmath>
#include <stdio.h>
#include <string>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <stack>
#include <queue>
#include <iomanip>
#include <algorithm>
#include <memory.h>
#define MAX 220
using namespace std;
struct P//不单独记录步数的结构体
{
    int r,c;
    P(int _r,int _c)
    {
        r=_r,c=_c;
    }
    P(){}
};

int n,m;//行,列
char Map[MAX][MAX];
int visit[MAX][MAX];
int min_step;//最小步数
int dirr[]={-1,1,0,0};//方向数组
int dirc[]={0,0,-1,1};
int time_Y[MAX][MAX],time_M[MAX][MAX];//分别记录两个人从起点到达任何一点的最短步数,如果不可到达,标记为-1
P Y,M,temp;//分别记录两个人的起点,以及一个全局temp变量,节省时间

void init()//初始化
{
    memset(time_Y,-1,sizeof(time_Y));
    memset(time_M,-1,sizeof(time_M));
    min_step=9999999;
}


void bfs_Y()//预处理yifenfei 的行走路线信息
{
    queue<P> q;
    q.push(Y);
    time_Y[Y.r][Y.c]=0;
    int r,c;
    int i;
    while(!q.empty())
    {
        temp=q.front();
        q.pop();
        for(i=0;i<4;i++)
        {
            r=temp.r+dirr[i];
            c=temp.c+dirc[i];
            if(r>=0&&r<n&&c>=0&&c<m&&Map[r][c]!='#'&&visit[r][c]==0)
            {
                visit[r][c]=1;
                q.push(P(r,c));
                time_Y[r][c]=time_Y[temp.r][temp.c]+11;
            }
        }
    }
}

void bfs_M()//预处理Ningbo 的路线信息
{
    queue<P> q;
    q.push(M);
    int i,r,c;
    time_M[M.r][M.c]=0;
    while(!q.empty())
    {
        temp=q.front();
        q.pop();
        for(i=0;i<4;i++)
        {
            r=temp.r+dirr[i];
            c=temp.c+dirc[i];
            if(r>=0&&r<n&&c>=0&&c<m&&Map[r][c]!='#'&&visit[r][c]==0)
            {
                visit[r][c]=1;
                q.push(P(r,c));
                time_M[r][c]=time_M[temp.r][temp.c]+11;
            }
        }
    }
}




int main()
{
    int i,j;
    while(cin>>n>>m)//如果用scanf,要加‘~’
    {
        init();
        for(i=0;i<n;i++)
        {
            scanf("%s",Map[i]);
            for(j=0;j<m;j++)
            {
                if(Map[i][j]=='Y')
                {
                    Y.r=i;
                    Y.c=j;
                }
                if(Map[i][j]=='M')
                {
                    M.r=i;
                    M.c=j;
                }
            }

        }
        memset(visit,0,sizeof(visit));
        bfs_Y();
        memset(visit,0,sizeof(visit));
        bfs_M();
        int time1,time2;
        for(i=0;i<n;i++)//遍历整个Map找出所有的KFC
        {
            for(j=0;j<m;j++)
            {
                if(Map[i][j]=='@'&&time_Y[i][j]!=-1&&time_M[i][j]!=-1)
                {
                    time1=time_Y[i][j];
                    time2=time_M[i][j];
                    if((time1+time2)<min_step)
                        min_step=time1+time2;
                }
            }
        }
        printf("%d\n",min_step);
    }
    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值