典型的广度优先搜索,
题意:图中Y代表起点,T代表终点,S代表铁墙,不可被击毁也不可被通过,B代表木墙,可以被击毁,击毁后可以通过,R代表河流,不可击毁也不可通过,E代表可通过。
击毁木墙会消耗一步,问最少多少步能从起点走到终点。
#include<stdio.h> //广度优先搜索
#include<iostream>
#include<string.h>
#include<queue>
#include<algorithm>
#define M 30
using namespace std;
char s[310][310];
bool vis[310][310];
struct node{
int x,y,step; // 坐标和时间
node(int x = 0,int y =0 ,int step= 0):x(x),y(y),step(step){};//相当于是一个构造函数
bool operator < (const node &a)const{
return step > a.step;
}
}st,ed;
/*
等价于如下
struct node{
int x,y,step;
node(int _x,int _y)
{
x = _x;
y = _y;
}
bool operator < (const node &a)
const {
return step > a.step;
}
}st,ed;*/
int dx[4] = {0,0,-1,1};
int dy[4] = {1,-1,0,0};//四个方向
int n,m;
int bfs(){
priority_queue<node>Q;
Q.push(st);
memset(vis,0,sizeof(vis));
while(!Q.empty()){
node now = Q.top();//目前的队首
Q.pop();
node nt;
for(int i=0;i<4;i++){
nt.x = now.x + dx[i];
nt.y = now.y + dy[i];
nt.step = now.step + 1;//找四个方向的
if(nt.x >=0 && nt.x < n && nt.y>=0 && nt.y<m&&!vis[nt.x][nt.y] ){//判断不要出界
if(s[nt.x][nt.y] == 'E'){
vis[nt.x][nt.y] = 1;
Q.push(nt);
}//是路 加一结果入队
else if(s[nt.x][nt.y] == 'T'){
return nt.step;
}//是目标返回时间
else if(s[nt.x][nt.y] == 'B'){
nt.step++; // 队列中的step不同
//因而优先队列是正解
vis[nt.x][nt.y] = 1;
Q.push(nt);
}//是障碍 加二结果入队
}
}
}
return -1;//没有结果
}
int main(){
while(scanf("%d%d",&n,&m)!=EOF &&(n || m)){
for(int i=0;i<n;i++) scanf("%s",s[i]);
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(s[i][j] == 'Y')
st.x = i,st.y = j;
else if(s[i][j] == 'T')
ed.x = i,ed.y = j;
}
}//找到起点和终点的坐标
st.step = 0;//起始时间置0
printf("%d\n",bfs());
}
return 0;
}