R . The Wall Pushers

Description

The figure below shows a maze with three exits. You are allowed to move between two squares within the maze if they are adjacent and 1) there is no wall separating the squares or 2) there is an inner wall between the squares, which may be pushed in the direction of movement. A wall can be pushed if there is no wall behind it. Notice that it’s not allowed to push any wall that lies on the boundary of the maze.

Find the shortest path from the start position (S) to any of the exit

From the start position (SS) in the figure above, it’s possible to move north or east, but not west or south. If moving north, the wall between the squares (2, 3) and (2, 2) will be moved to the position between the squares (2, 2) and (2, 1). At this new position, it’s not possible to move north again because there is a wall north of (2, 1).

Write a program that finds the shortest path from a given start position to any of the exits. You may assume there exists at least one solution for each maze.

Input

The input file may contain several mazes to solve. Each maze description starts with a single line containing two integers xx and yy (1≤x≤61≤x≤6, 1≤y≤41≤y≤4) which is the start position in the maze. Next follows four lines with six integers each. These integers pp (0≤p≤150≤p≤15) describe each square in the maze in the following way: pp is the sum of 1 (if there is a wall west of the square), 2 (north), 4 (east) and 8 (south). Each inner wall will thus be mentioned twice. Each opening in the  oundary is considered an exit.

The input ends with a maze with starting coordinates 0, 0 and should not be processed.

Output

Output a single line for each maze with the description of a path with minimum length that leads to any of exits. Use the letters ‘N’, ‘S’, ‘E’ and ‘W’ to denote north, south, east and west, respectively. If there are several solutions with minimum length, display any one of them.

Samples

Input 复制

2 3
10 2 10 10 2 6
3 12 11 14 9 4
13 15 3 6 15 13
14 11 12 9 14 11
0 0

Output

NESESEENNWNWWWWW

描述
下图显示了一个有三个出口的迷宫。你可以在迷宫中的两个方格之间移动,如果它们相邻,并且1)方格之间没有隔离墙,或者2)方格之间有一个内壁,可以朝着移动的方向推动。如果后面没有墙,墙是可以推倒的。请注意,不允许推迷宫边界上的任何墙。
找出从起始位置到任何出口的最短路径
从上图中的起始位置,可以向北或向东移动,但不能向西或向南移动。如果向北移动,正方形(2,3)和(2,2)之间的墙将移动到正方形(2,2)和(2,1)之间的位置。在这个新位置,不可能再向北移动,因为(2,1)以北有一堵墙。
编写一个程序,找出从给定的起始位置到任意出口的最短路径。你可以假设每个迷宫至少有一个解。
输入
输入文件可能包含几个要解决的迷宫。每个迷宫描述都从一行开始,其中包含两个整数x和y(1)≤十≤6, 1≤Y≤4) 这是迷宫的起始位置。接下来是四行,每行有六个整数。这些整数p(0≤P≤15) 用以下方式描述迷宫中的每个正方形:p是1(如果在正方形的西边有墙)、2(北)、4(东)和8(南)的和。因此,每个内壁将被提及两次。边界上的每个开口都被视为出口。
输入以起始坐标为0的迷宫结束,不应进行处理。
输出
为每个迷宫输出一行,描述通向任何出口的最小长度路径。用字母“N”、“S”、“E”和“W”分别表示北、南、东和西。如果有多个最小长度的解决方案,请显示其中任何一个。
样品
输入复制
2 3
10 2 10 10 2 6
3 12 11 14 9 4
13 15 3 6 15 13
14 11 12 9 14 11
0 0
输出
NESESEENNWNWWWWW

方法:迭代加深搜

#include<iostream>
#include<time.h>
#include<queue>
#include<stdlib.h>
#include<string.h>
using namespace std;
int direction[] = { 1,2,4,8 };
int dr[] = { 0,-1,0,1 };
int dc[] = { -1,0,1,0 };
char rr[] = { 'W','N','E','S' };
int row, col;
int maxd;
int vis[10][10];
int map[10][10];
char route[100];
bool solve(int r,int c,int dep,int dir) {
	if (dep >= maxd)return false;
		for (int i = 0; i < 4; i++) {
			if (dir!=-1&&i == dir)continue;
			int ddr = r, ddc = c;
			ddr += dr[i];
			ddc += dc[i];
			if ((map[r][c] & direction[i]))
			{
				if (ddr >= 1 && ddr <= 4 && ddc >= 1 && ddc <= 6) {
					if (map[ddr][ddc] & direction[i])
						continue;//前方有墙
					else {
						int k = i; k ^= 2;
						map[r][c] ^= direction[i];//-
						map[ddr][ddc] ^= direction[i];//+
						map[ddr][ddc] ^= direction[k];//-
						map[ddr + dr[i]][ddc + dc[i]] ^= direction[k];//+
						route[dep] = rr[i];
						if (solve(ddr, ddc, dep + 1,i^2))return true;
					
						map[r][c] ^= direction[i];//-
						map[ddr][ddc] ^= direction[i];//+
						map[ddr][ddc] ^= direction[k];//-
						map[ddr + dr[i]][ddc + dc[i]] ^= direction[k];//+
					}
				}
				else continue;//有墙且越界
			}
			else {
				if (ddr < 1 || ddr>4 || ddc < 1 || ddc>6) {
					for (int j = 0; j < dep; j++) {
						cout << route[j];
					}
					cout <<rr[i]<< endl;
					return true;
				}
				route[dep] = rr[i];
				if (solve(ddr, ddc, dep + 1, i ^ 2))return true;
			}
	    }
		return false;
}
int main() {
	while (cin >> col >> row&&col&&row) {
		for (int i = 1; i <= 4; i++)
			for (int j = 1; j <= 6; j++)
				cin >> map[i][j];
		for (maxd = 1;; maxd++) {
			if (solve(row,col,0,-1))break;
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值