问题描述
给定一个R行C列的地图,地图的每一个方格可能是'#', '+', '-', '|', '.', 'S', 'T'七个字符中的一个,分别表示如下意思:
'#': 任何时候玩家都不能移动到此方格;
'+': 当玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格;
'-': 当玩家到达这一方格后,下一步可以向左右两个方向相邻的一个非'#'方格移动一格;
'|': 当玩家到达这一方格后,下一步可以向上下两个方向相邻的一个非'#'方格移动一格;
'.': 当玩家到达这一方格后,下一步只能向下移动一格。如果下面相邻的方格为'#',则玩家不能再移动;
'S': 玩家的初始位置,地图中只会有一个初始位置。玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格;
'T': 玩家的目标位置,地图中只会有一个目标位置。玩家到达这一方格后,可以选择完成任务,也可以选择不完成任务继续移动。如果继续移动下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格。
此外,玩家不能移动出地图。
请找出满足下面两个性质的方格个数:
1. 玩家可以从初始位置移动到此方格;
2. 玩家不可以从此方格移动到目标位置。
输入格式
输入的第一行包括两个整数R 和C,分别表示地图的行和列数。(1 ≤ R, C ≤ 50)。
接下来的R行每行都包含C个字符。它们表示地图的格子。地图上恰好有一个'S'和一个'T'。
输出格式
如果玩家在初始位置就已经不能到达终点了,就输出“I'm stuck!”(不含双引号)。否则的话,输出满足性质的方格的个数。
样例输入
5 5
--+-+
..|#.
..|##
S-+-T
####.
样例输出
2
样例说明
如果把满足性质的方格在地图上用'X'标记出来的话,地图如下所示:
--+-+
..|#X
..|##
S-+-T
####X
题解
正着一遍bfs反着一遍bfs!
AC代码
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
int n,m;
bool reached1[55][55];
bool reached2[55][55];
char a[55][55];
int num=0;
void bfs1(int x,int y){
reached1[x][y]=true;
vector<int>dir;
switch (a[x][y]){
case 'S':
case 'T':
case '+':
dir.push_back(-1);
dir.push_back(0);
dir.push_back(1);
dir.push_back(0);
dir.push_back(0);
dir.push_back(-1);
dir.push_back(0);
dir.push_back(1);
break;
case '-':
dir.push_back(0);
dir.push_back(-1);
dir.push_back(0);
dir.push_back(1);
break;
case '|':
dir.push_back(-1);
dir.push_back(0);
dir.push_back(1);
dir.push_back(0);
break;
case '.':
dir.push_back(1);
dir.push_back(0);
break;
}
for(int i=0;i<dir.size();i+=2){
int dirx=dir[i];
int diry=dir[i+1];
int nx=x+dirx;
int ny=y+diry;
if(nx>=0&&nx<n&&ny>=0&&ny<m){
if(a[nx][ny]=='#'||reached1[nx][ny]){
continue;
}else{
bfs1(nx,ny);
}
}else continue;
}
}
void bfs2(int x,int y){
reached2[x][y]=true;
vector<int>dir;
//shift+tab缩退
//倒着走不跟正着走一样,
//有很多需要仔细分析的地方,不是说简单的自以为是 这么简单的!!!!!!!
//又**的把n 和m忘记了,别傻了!!!
dir.push_back(-1);
dir.push_back(0);
dir.push_back(1);
dir.push_back(0);
dir.push_back(0);
dir.push_back(-1);
dir.push_back(0);
dir.push_back(1);
for(int i=0;i<dir.size();i+=2){
int dirx=dir[i];
int diry=dir[i+1];
int nx=x+dirx;
int ny=y+diry;
if(dirx==-1&&diry==0){//往上走时,上面面不能为-
if(nx>=0&&nx<n&&ny>=0&&ny<m){
if(a[nx][ny]=='-'||a[nx][ny]=='#'||reached2[nx][ny]){
continue;
}else{
bfs2(nx,ny);
}
}else continue;
}else if(dirx==1&&diry==0){//往下走时,下面不能为.或-
if(nx>=0&&nx<n&&ny>=0&&ny<m){
if(a[nx][ny]=='-'||a[nx][ny]=='.'||a[nx][ny]=='#'||reached2[nx][ny]){
continue;
}else{
bfs2(nx,ny);
}
}else continue;
}else{ //左右走时,不能为| 或.
if(nx>=0&&nx<n&&ny>=0&&ny<m){
if(a[nx][ny]=='|'||a[nx][ny]=='.'||a[nx][ny]=='#'||reached2[nx][ny]){
continue;
}else{
bfs2(nx,ny);
}
}else continue;
}
}
}
int main(){
cin>>n>>m;
int x1,y1,x2,y2;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin>>a[i][j];
if(a[i][j]=='S'){x1=i;y1=j;}
if(a[i][j]=='T'){x2=i;y2=j;}
}
}
bfs1(x1,y1);
bfs2(x2,y2);
// for(int i=0;i<n;i++){
// for(int j=0;j<m;j++){
// if(reached1[i][j])cout<<"1";else cout<<" ";
// }cout<<endl;
// }
// for(int i=0;i<n;i++){
// for(int j=0;j<m;j++){
// if(reached2[i][j])cout<<"1";else cout<<" ";
// }cout<<endl;
// }
//
if(!reached1[x2][y2]){
cout<<"I'm stuck!";
return 0;
}
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(reached1[i][j]&&!reached2[i][j]){
num++;
}
}
}
cout<<num;
return 0;
}