ACM H-8 廣度優先搜尋(BFS)
阿新 • • 發佈:2021-01-21
最近在家上網課的zst由於把switch放在了寢室所以實在無聊透頂,便拉著str一起玩一款名叫《風來的西林》的遊戲,在某次刷圖的過程中,由於zst炸裂的歐氣,一張地圖中同時出現了數把螺旋風魔劍,但此劍需要zst和str兩人合力才可取得。
由於這款遊戲是按時間付費的,所以兩人需要儘快取得此劍(即為二人到達劍所在位置的時間之和最少),因此他們找到了機智的你來幫忙解決問題。
Input
多組資料讀入到檔案結束 每組資料的第一行輸入兩個整數n, m(2 <= n, m <= 200),即迷宮大小為n*m 接下來n行,每行包括m個字元 'Y'表示zst所在位置 'M'表示str所在位置 '.'表示可以行走的道路 '#'表示不可通過的牆壁 '@'表示螺旋風魔劍所在位置(數量多於一把) 二人每次行動只有上下左右四種方式,每次行動花費11個單位時間
Output
每組樣例輸出一行一個整數:二人到達同一把劍所在位置的最小時間之和。
保證有解
Sample Input
3 3
[email protected]
#..
@.M
Sample Output
44
注意: 有一個測試點是劍周圍都是牆體無法拿取。
#include<iostream>
#include<string.h>
#include<queue>
using namespace std;
char map[202][202];//地圖
int n,m;//n*m的陣列
int a[202][202],b[202][202];//分別對應Y,M兩個人
int yidong[4][2]={{1,0},{-1,0},{0,1},{0,-1}};//移動陣列,對應上下右左
struct node{
int x,y;
};
bool pd(int x,int y,int luxian[202][202])//判斷能否移動
{
if(x<0||x>=n||y<0||y>=m)//判斷邊界
return false;
if(luxian[x][y]!=0)//判斷是否走過
return false;
if(map[x][y]=='#')//判斷是否能通行
return false;
return true;
}
void bfs(int x,int y,int luxian[202][202])//廣度優先搜尋(BFS)
{
queue<node>q;//建立佇列
node next,last;//建立next為此佇列值,last為前一個佇列值
next.x=x;next.y=y;//對此佇列值賦值
luxian[x][y]=0;
q.push(next);//放入佇列
while(!q.empty())//不為空就繼續
{
last=q.front();//計入佇列頭的值
q.pop();//推出
for(int i=0;i<4;i++)//上下左右四個方向移動
{
next.x=last.x+yidong[i][0];//x移動值
next.y=last.y+yidong[i][1];//y移動值
if(pd(next.x,next.y,luxian))//判斷是否能走
{
luxian[next.x][next.y]=luxian[last.x][last.y]+1;//沿路做標記
q.push(next);//放入佇列
}
}
}
}
int main()
{
int i,j,ydmin,yx,yy,mx,my;
while(cin>>n>>m)//此題為多組輸入
{
ydmin=1000000;//哨兵
memset(a,0,sizeof(a));//來自string標頭檔案
memset(b,0,sizeof(b));//因為多組輸入所以要對a,b陣列清空處理
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
cin>>map[i][j];
if(map[i][j]=='Y')//記錄Y地址
{
yx=i;yy=j;
}
else if(map[i][j]=='M')//記錄M地址
{
mx=i;my=j;
}
}
}
bfs(yx,yy,a);//Y開始廣搜
bfs(mx,my,b);//M開始廣搜
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
if(map[i][j]=='@'&&a[i][j]!=0)//有一個測試點是a[i][j]+b[i][j]=0
{
ydmin=min(ydmin,a[i][j]+b[i][j]);
}
}
}
cout<<ydmin*11<<endl;
}
return 0;
}