问题描述
给定一个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
解题思路:
从S出发找到所有能到的点,从T出发,逆着过程找到所有能到T的点。
关键:如何从T开始逆着过程找能到T的点。
如果当前点的某一方向有点x,那么该x必须要满足能走到当前点,才能继续从x为起点搜索下去。
如当前点的上方有一点,那么上方的点必须要有往下走能力才能算从上方的点能走到T。
tips:
1.在深搜过程不主动return,最后会根据限制条件走遍所有能走的点;
2.vis数组直接用来保存能到的点,在回溯时不用置0。因为只要考虑能否走到某一点;
3.如果不逆过程,而是对每一个点都进行一遍搜索看能否到T,会超出时间限制。
参考代码
#include<iostream>
#include<string.h>
using namespace std;
int r = 0,c = 0;
int dir[4][2] = {{0,-1}, {0, 1}, {-1,0}, {1, 0}};//左 右 上 下
int flag = 0;
char map[55][55];
bool visS[55][55],visT[55][55];//visS用于记录s点出发能到的所有点 ,visT用于记录能到T的点
int inbod(int x, int y)
{
return x < r && x >= 0 && y < c && y >=0;
}
void dfsS(int x,int y)
{
visS[x][y] = 1;
if(map[x][y] == 'T') {//找到T
flag = 1;
}
//按方向划分 左右上下
if (map[x][y] == 'S' || map[x][y] == '-' || map[x][y] == '+' || map[x][y] == 'T') {
if (inbod(x, y - 1) && !visS[x][y - 1] && map[x][y - 1] != '#') {
dfsS(x, y - 1);
}
}
if (map[x][y] == 'S' || map[x][y] == '-' || map[x][y] == '+' || map[x][y] == 'T') {
if (inbod(x, y + 1) && !visS[x][y + 1] && map[x][y + 1] != '#') {
dfsS(x, y + 1);
}
}
if (map[x][y] == 'S' || map[x][y] == '+' || map[x][y] == 'T' || map[x][y] == '|') {
if (inbod(x - 1, y) && !visS[x - 1][y] && map[x - 1][y] != '#') {
dfsS(x - 1, y);
}
}
if (map[x][y] == 'S' || map[x][y] == '.' || map[x][y] == '+' || map[x][y] == 'T' || map[x][y] == '|') {
if (inbod(x + 1, y) && !visS[x + 1][y] && map[x + 1][y] != '#') {
dfsS(x + 1, y);
}
}
}
void dfsT(int x,int y)
{
visT[x][y] = 1;
for (int i = 0; i < 4; i++)
{
int tx, ty;
tx = x + dir[i][0];
ty = y + dir[i][1];
if(inbod(tx, ty) && map[tx][ty] != '#') {
if(i == 0 && (map[tx][ty] == 'S' || map[tx][ty] == '-' || map[tx][ty] == '+' || map[tx][ty] == 'T') && visT[tx][ty] == 0) dfsT(tx, ty);//在当前点左边的点,该点必须要有往右的能力
if(i == 1 && (map[tx][ty] == 'S' || map[tx][ty] == '-' || map[tx][ty] == '+' || map[tx][ty] == 'T' ) && visT[tx][ty] == 0) dfsT(tx, ty);
if(i == 2 && (map[tx][ty] == 'S' || map[tx][ty] == '.' || map[tx][ty] == '+' || map[tx][ty] == 'T' || map[tx][ty] == '|') && visT[tx][ty] == 0) dfsT(tx, ty);
if(i == 3 && (map[tx][ty] == 'S' || map[tx][ty] == '+' || map[tx][ty] == 'T' || map[tx][ty] == '|') && visT[tx][ty] == 0) dfsT(tx, ty);//在当前点下面,该点必须要有往上的能力
}
}
}
int main()
{
int sx = 0,sy = 0, ex = 0, ey = 0;
cin >> r >> c;
for (int i= 0; i < r; i++) {
for (int j = 0; j < c; j++) {
cin >> map[i][j];
if(map[i][j] == 'S') {
sx = i;
sy = j;
}
if(map[i][j] == 'T') {
ex = i;
ey = j;
}
}
}
dfsS(sx, sy);
if (flag == 0) {//能否找到T
cout << "I'm stuck!";
return 0;
}
dfsT(ex, ey);//从T开始,逆找能到T的点
int cnt = 0;
for (int i= 0; i < r; i++) {
for (int j = 0; j < c; j++) {
if (visS[i][j] == 1 && visT[i][j] == 0) {//S能到,且不能到T
cnt ++;
}
}
}
cout << cnt;
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!