问题描述
给定一个R行C列的地图,地图的每一个方格可能是'#', '+', '-', '|', '.', 'S', 'T'七个字符中的一个,分别表示如下意思:
'#': 任何时候玩家都不能移动到此方格;
'+': 当玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格;
'-': 当玩家到达这一方格后,下一步可以向左右两个方向相邻的一个非'#'方格移动一格;
'|': 当玩家到达这一方格后,下一步可以向上下两个方向相邻的一个非'#'方格移动一格;
'.': 当玩家到达这一方格后,下一步只能向下移动一格。如果下面相邻的方格为'#',则玩家不能再移动;
'S': 玩家的初始位置,地图中只会有一个初始位置。玩家到达这一方格后,下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格;
'T': 玩家的目标位置,地图中只会有一个目标位置。玩家到达这一方格后,可以选择完成任务,也可以选择不完成任务继续移动。如果继续移动下一步可以向上下左右四个方向相邻的任意一个非'#'方格移动一格。
此外,玩家不能移动出地图。
请找出满足下面两个性质的方格个数:
1. 玩家可以从初始位置移动到此方格;
输入的第一行包括两个整数R 和C,分别表示地图的行和列数。(1 ≤ R, C ≤ 50)。
--+-+
..|#.
..|##
S-+-T
如果把满足性质的方格在地图上用'X'标记出来的话,地图如下所示:
--+-+
..|#X
..|##
S-+-T
代码经CCF平台测试,时间花费为 0ms ,得分100分。
给定一个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
题目分析:
比较简单的一道图论题目,从起点出发的可达的点利用深搜或者广搜都可以做到,求哪些点可以到达终点时,网上多数做法是对矩阵中每一个点做一次深搜或广搜,但是这样效率很低。
本文在求哪些点可到终点时,反向思考从终点出发可以到达哪些点,修改部分规则,比如遇到'.',我们必须确保是从下方走上来的,才可以回去。遇到'-',认为必须从左右来,遇到'|',认为必须从上下来。
代码如下:
#include <iostream>
#include <memory.h>
using namespace std;
#define DIM 50
//正向深搜,从起点出发
void ForwardDFS(char map[DIM][DIM],//输入矩阵
bool sign[DIM][DIM],//返回标记结果图,true表示可以到达这个点,false表示不能到达
int Row,int Col,//矩阵规模
int curR, int curC)//当前点
{
//若 当前点已走过 或 当前点是障碍物,停止递归
if (sign[curR][curC] || map[curR][curC] == '#')
{
return ;
}
//标记此点可达
sign[curR][curC] = true;
//标记可以往哪个方向移动
bool up,down,left,right;
up = down = left = right = false;
if (map[curR][curC] == '.')//向下移动
{
down = true;
}
else if (map[curR][curC] == '-')//左右移动
{
left = right = true;
}
else if (map[curR][curC] == '|')//上下移动
{
up = down = true;
}
else if (map[curR][curC] == '+' || map[curR][curC] == 'S' || map[curR][curC] == 'T')//上下左右移动
{
up = down = left = right = true;
}
//上
if (up && curR-1 >= 0)
{
ForwardDFS(map,sign,Row,Col,curR-1,curC);
}
//下
if (down && curR+1 < Row)
{
ForwardDFS(map,sign,Row,Col,curR+1,curC);
}
//左
if (left && curC-1 >= 0)
{
ForwardDFS(map,sign,Row,Col,curR,curC-1);
}
//右
if (right && curC+1 < Col)
{
ForwardDFS(map,sign,Row,Col,curR,curC+1);
}
}
//从终点出发,反向DFS
void ReserveDFS(char map[DIM][DIM],//输入矩阵
bool sign[DIM][DIM],//返回标记结果图,true表示可以到达这个点,false表示不能到达
int Row,int Col,//矩阵规模
int curR, int curC,//当前点
int preR, int preC)//上一个点
{
//若 当前点已走过 或 当前点是障碍物,停止递归
if (sign[curR][curC] || map[curR][curC] == '#')
{
return ;
}
//从下面来的,可以返回去,其他方向来的无法原路返回
if (map[curR][curC] == '.' && preR == curR+1 && preC == curC)
{
sign[curR][curC] = true;
}
//从左右来的可以返回去
else if (map[curR][curC] == '-' && preR == curR)
{
sign[curR][curC] = true;
}
//必须从上下来
else if (map[curR][curC] == '|' && preC == curC)
{
sign[curR][curC] = true;
}
//可随便返回
else if (map[curR][curC] == 'S' || map[curR][curC] == '+' || map[curR][curC] == 'T')
{
sign[curR][curC] = true;
}
//不可达,返回
if (sign[curR][curC] == false)
{
return ;
}
//上
if (curR-1 >= 0)
{
ReserveDFS(map,sign,Row,Col,curR-1,curC,curR,curC);
}
//下
if (curR+1 < Row)
{
ReserveDFS(map,sign,Row,Col,curR+1,curC,curR,curC);
}
//左
if (curC-1 >= 0)
{
ReserveDFS(map,sign,Row,Col,curR,curC-1,curR,curC);
}
//右
if (curC+1 < Col)
{
ReserveDFS(map,sign,Row,Col,curR,curC+1,curR,curC);
}
}
int main()
{
int R,C;
cin>>R>>C;
char map[DIM][DIM];
bool sCanReach[DIM][DIM];//起点能到达的矩阵
bool tCanReach[DIM][DIM];//终点能到的矩阵
for (int i=0; i<R; i++)
{
for (int j=0; j<C; j++)
{
cin>>map[i][j];
}
}
memset(sCanReach,0,DIM*DIM);
memset(tCanReach,0,DIM*DIM);
//处理
for (int i=0; i<R; i++)
{
for (int j=0; j<C; j++)
{
if (map[i][j] == 'S')
{
ForwardDFS(map,sCanReach,R,C,i,j);
}
}
}
for (int i=0; i<R; i++)
{
for (int j=0; j<C; j++)
{
if (map[i][j] == 'T')
{
if (sCanReach[i][j] == false)
{
cout<<"I'm stuck!"<<endl;
return 0;
}
ReserveDFS(map,tCanReach,R,C,i,j,i,j);
}
}
}
int num = 0;
/* for (int i=0; i<R; i++)
{
for (int j=0; j<C; j++)
{
cout<<map[i][j]<<" ";
}
cout<<endl;
}
for (int i=0; i<R; i++)
{
for (int j=0; j<C; j++)
{
cout<<sCanReach[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
for (int i=0; i<R; i++)
{
for (int j=0; j<C; j++)
{
cout<<tCanReach[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
*/
for (int i=0; i<R; i++)
{
for (int j=0; j<C; j++)
{
if (map[i][j] != 'S' && map[i][j] != 'T' &&
sCanReach[i][j] && !tCanReach[i][j])
{
num++;
}
}
}
cout<<num<<endl;
return 0;
}
代码经CCF平台测试,时间花费为 0ms ,得分100分。