CCF CSP 201312-5 I’m stuck!

试题编号: 201312-5
试题名称: I’m stuck!
时间限制: 1.0s
内存限制: 256.0MB
问题描述:   给定一个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

思路:

1.用二维数组存储这个地图,然后分别进行两次dfs;
2.分别用两个二维数组存储各个坐标是否可以从起点走到bool mvTo[55][55]、各个坐标是否可以走到终点bool toEnd[55][55]
3.第一次dfs:起点从题目给的起点开始,往后dfs,每遍历到一个坐标,更新mvTo数组;第二次dfs:起点从题目给的终点开始,往前dfs,每遍历到一个坐标,更新toEnd数组;
4.注意第二次dfs的时候不是往下走,是倒着走,需要注意规则的变换;
5.最后遍历所有坐标,输出从起点可达且不可达到终点的坐标数量;

代码:

#define IOS ios_base::sync_with_stdio(0); cin.tie(0);
#include<iostream>
using namespace std;
int r,c,si,sj,ti,tj;
char Map[55][55];
bool mvTo[55][55],toEnd[55][55];
bool isLegal(int i,int j){
	if(i>=1&&i<=r&&j>=1&&j<=c&&Map[i][j]!='#'&&!mvTo[i][j]) return true;
	else return false;
}
bool risLegal(int i,int j){
	if(i>=1&&i<=r&&j>=1&&j<=c&&!toEnd[i][j]) return true;
	else return false;
}
void dfs(int i,int j){
	mvTo[i][j]=true;
	char c=Map[i][j];
	if(c=='+'||c=='|'||c=='S'||c=='T'||c=='.'){
		if(c!='.'&&isLegal(i-1,j)) dfs(i-1,j);
		if(isLegal(i+1,j)) dfs(i+1,j);
	}
	if(c=='+'||c=='-'||c=='S'||c=='T'){
		if(isLegal(i,j-1)) dfs(i,j-1);
		if(isLegal(i,j+1)) dfs(i,j+1);
	}
}
void rdfs(int i,int j){
	toEnd[i][j]=true;
	char c=Map[i-1][j];
	if(risLegal(i-1,j)&&(c=='+'||c=='|'||c=='S'||c=='T'||c=='.')) rdfs(i-1,j);
	c=Map[i+1][j];
	if(risLegal(i+1,j)&&(c=='+'||c=='|'||c=='S'||c=='T')) rdfs(i+1,j);
	c=Map[i][j-1];
	if(risLegal(i,j-1)&&(c=='+'||c=='-'||c=='S'||c=='T')) rdfs(i,j-1);
	c=Map[i][j+1];
	if(risLegal(i,j+1)&&(c=='+'||c=='-'||c=='S'||c=='T')) rdfs(i,j+1);
}
int main(){
	IOS;
	cin>>r>>c;
	for(int i=1;i<=r;i++){
		for(int j=1;j<=c;j++){
			cin>>Map[i][j];
			if(Map[i][j]=='S') {si=i;sj=j;}
			if(Map[i][j]=='T') {ti=i;tj=j;}
		}
	}
	dfs(si,sj);
	rdfs(ti,tj);
	if(!toEnd[si][sj]) cout<<"I'm stuck!";
	else{
		int cnt=0;
		for(int i=1;i<=r;i++)
			for(int j=1;j<=c;j++)
				if(mvTo[i][j]&&!toEnd[i][j]) cnt++;
		cout<<cnt;
	}
	return 0;
}
原文地址:https://www.cnblogs.com/yuhan-blog/p/12308954.html