递归——左手定则

描述
玩过RPG(尤其是国产RPG)的童鞋都应该对迷宫这种神棍的设定深恶痛绝,尤其是当你转了半小时之后发现回到了原地,这种感觉真是无比的痛苦。。。万一游戏还中途崩溃了那真是连掀桌子、砸键盘、摔鼠标的心都有了……
经过无数次的TRIAL AND ERROR之后,玩家终于下定决心认定迷宫存在的意义就是延长游戏时间,SO,他决定借鉴著名的左手定则(就是在每一个路口,我们都选择最左边的方向,左转的优先级最高,其次为向前,最后为右转,如果实在走进了一个死胡同,那就连续右转两次,回头向后走。稍微研究一下这种走迷宫的方法,我们就发现在这个过程中,事实上我们的左手可以始终放在墙上。)对迷宫进行探索。
但是呢,左手定则并不能保证遍历到迷宫中的每一个点。悲剧的是,某项重要的通关道具被放在了这个迷宫中……幸运的是,游戏迷宫的地图可以绘制出来,现在请求你的帮助。对于一个给定的地图,他想知道是不是能够通过左手定则取得这件道具。
关于输入
多组数据。
对于每组数据,第一行有两个整数N,M代表接下来有n行字符串,每行m个字符,其中0其中‘#’表示墙,‘S’表示起点,‘T’表示道具,‘.’表示空地。
接下来是一个方向(NSWE),表示起始面向的方向。
数据保证最外一圈都是墙。
关于输出
对于每组数据输出一行。‘YES’表示可以到达,‘NO’表示无法到达。
例子输入
8 10

##########

#...T....#

#.####...#

#.#..#.#.#

#.#....#.#

#.####.#.#

#......#S#

##########

N



8 10

##########

#........#

#.####...#

#.#T.#.#.#

#.#....#.#

#.####.#.#

#......#S#

##########

N

8 10

##########

#....#...#

#..#.#...#

#..#.....#

#..#.#S###

#..#.#...#

#....#T..#

##########

N

例子输出
YES

NO

YES
提示
E东
S南
W西
N北

不会原地转圈

如何判断找不到呢?

我采用的方法是判断它如果到达起点多次(至少比2大吧),则说明它找不到T(不然早就返回“YES”了)

①选择起点是因为起点的位置已经记录过,便于取出调用

②注意!!如果认为第二次到达起点即判定为找不到是错误的,如样例的第二组输入。

#include<iostream>
#include<cstring>
using namespace std;
char map[100][100];
int n,m;
int strow = 0, stcol = 0;//记录出发位置的行与列
char direct;//出发位置时的方向
bool flag = 0;//用来记录是否已经找到T
int xflag = 0;//用来记录是否重复到达起点多次
void go(int row, int col, char dirc)//目前所处位置的行、列、方向
{
	if (map[row][col] == 'T') {//找到了T
		cout << "YES" << endl;
		flag = 1;
		return;
	}
	if (map[row - 1][col] == '#' && map[row][col - 1] == '#' &&//如果四周都是墙..
		map[row][col + 1] == '#' && map[row + 1][col] == '#') {
		return;
	}
	if (map[row][col] == 'S') {//如果再次到达起点S
		++xflag;
	}
	if (xflag == 3) {//如果多次到达起点S,说明找不到T,返回
		return;
	}
	if (dirc == 'S') {
		if (map[row][col + 1] != '#') { go(row, col + 1, 'E'); }
		else if (map[row][col + 1] == '#' && map[row + 1][col] != '#') {
			go(row + 1, col, 'S');
		}
		else if (map[row][col + 1] == '#' && map[row + 1][col] == '#' && map[row][col - 1] != '#') {
			go(row, col - 1, 'W');
		}
		else {
			go(row - 1, col, 'N');
		}
	}
	else if (dirc == 'N') {
		if (map[row][col - 1] != '#') { go(row, col - 1, 'W'); }
		else if (map[row][col - 1] == '#' && map[row - 1][col] != '#') {
			go(row - 1, col, 'N');
		}
		else if (map[row][col - 1] == '#' && map[row - 1][col] == '#' && map[row][col + 1] != '#') {
			go(row, col + 1, 'E');
		}
		else {
			go(row + 1, col, 'S');
		}
	}
	else if (dirc == 'W') {
		if (map[row + 1][col] != '#') { go(row + 1, col, 'S'); }
		else if (map[row + 1][col] == '#' && map[row][col - 1] != '#') {
			go(row, col - 1, 'W');
		}
		else if (map[row + 1][col] == '#' && map[row][col - 1] == '#' && map[row - 1][col] != '#') {
			go(row - 1, col, 'N');
		}
		else {
			go(row, col + 1, 'E');
		}
	}
	else if (dirc == 'E') {
		if (map[row - 1][col] != '#') { go(row - 1, col, 'N'); }
		else if (map[row - 1][col] == '#' && map[row][col + 1] != '#') {
			go(row, col + 1, 'E');
		}
		else if (map[row - 1][col] == '#' && map[row][col + 1] == '#' && map[row + 1][col] != '#') {
			go(row + 1, col, 'S');
		}
		else {
			go(row, col - 1, 'W');
		}
	}
}
int main()
{
	while (cin >> n >> m) {
		flag = 0;
		xflag = 0;
		for (int i = 0; i < n; ++i) {
			for (int j = 0; j < m; ++j) {
				cin >> map[i][j];
				if (map[i][j] == 'S') {
					strow = i;
					stcol = j;
				}
			}
		}
		cin >> direct;
		go(strow, stcol, direct);
		if (flag == 0)	cout << "NO" << endl;
	}
	return 0;
}

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值