D - DomiNo Grid ZOJ - 2925

D - DomiNo Grid

 ZOJ - 2925 

Dominoes are small, flat, rectangular-shaped game pieces. Domino pieces are usually twice as long as they are wide and are usually made to be exactly half as thick as they are wide so that they can stand on edge without falling over. If we push one end of a queue of dominoes, the whole queue will fall over.

 

Now, you will be given some descriptions of domino grid with a '.' indicating an open space and an uppercase 'X' indicating a domino and the force used on one domino. You are to compute the ending descriptions. The force consists of two parts : location and direction. There are 8 directions shown below.

direction abbreviation
West : W
NorthWest : V
North : N
NorthEast : Y
East : E
SouthEast : Q
South : S
SouthWest : J

The falling direction of the pushed domino is always the same as the force. Other dominoes will fall over if: 1) it's adjacent with a previous fallen domino. 2) it's within 45 degree of the falling direction of the previous domino.

The direction of falling is the relative position of it to the previous fallen domino. No two dominoes will cause the same domino to fall over simultaneously. See the following example for more details.

XXX 
XXX 
XXX 

We say the outer 8 dominoes are adjacent with the middle one. With a force to east on the middle domino, the 3 dominoes in the third column will fall over and the direction will be northeast, east, southeast. So the ending grid is :

XXY 
XEE 
XXQ 

Input

There are multiple test cases. Each case begins with a line containing two positive integer n and m (1 <= n, m <= 500) that are the number of rows and columns of the grid. The next n lines each with m chars (only '.' and 'X') describe one row of the grid. At last, two integers i, j (ith row, jth column, both i and j start from 1) indicate the location of the force and a char C describes the direction of the force. You can assume that there is a domino at the location (i, j).

Process to the end of file.

Output

Print the ending description of the grid, using the abbreviations for the fallen dominoes.

Print a blank line between cases.

Sample Input

2 4
..XX
XX..
1 3 S
4 4
XXX.
...X
X..X
XXX.
3 1 E

Sample Output

..SX
WJ..

WWV.
...N
E..Y
XQE.

题目大意:

在一个map里,推动一个骨牌,他会带动即正前方、左侧45度和右侧45度的骨牌倒下,问当推动其中一个骨牌的时候,对应最后在map里倒下骨牌的方向和情况。

解题思路

从起始骨牌开始,不断将相邻的倒下骨牌的倾倒方向记录下来,直至没有新倒下的骨牌。用一个先进先出队列queue<Node> q保存已倒下但它引发的其它骨牌尚未处理的骨牌。队列的元素类型Node是格点的二维坐标。用二维地图类广搜的方式处理所有已倒下的骨牌,直至队列变空。广搜的解空间树是一个三叉树,每个结点最多扩展成3个新结点,分别是正前方、左侧45度和右侧45度的相邻格点。一旦新格点是合法格点且未曾倒下(标记是“X”),标记它倒下的方向。流程图如下。

 

用一个目标型二维数组记录倒下方向,为方便程序处理,倒下方向用序号0~7表示,因为记录格点矩阵的问题描述型二维数组仅出现“.”和“X”两种字符,与0~7不冲突,所以这两个数组可以合并,统一到一个字符型数组。

实现技巧:

(1)方向序号0~7,表示从East开始的8个逆时针排列的方向。在这种0-based的表示方式下,若当前方向为d,则三个新方向是(d-k+8) % 8 (k=-1, 0, 1),例如d=0(East),则三个新方向是7,0,1。

(2) 8个方向的序号和位移量如下图,用一个二维数组moves[8][2]表示:

       int moves[8][2] = {{1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1} };

则d方向的位移量(x,y)=(moves[d][0], moves[d][1])。

 

 

(3)方向字符需要转换为序号,方向序号也需要转换为字符。利用下面字符串及内联函数

char DirectChar[9] = "EYNVWJSQ";

inline int FromCharToNo(char dch)

{     return strchr(DirectChar, dch) - DirectChar;  }

可以实现双向的简洁转换。

序号d→字符:DirectChar[d];

字符dch→序号:fromCharToNo(dch)。

参考代码:

#include <string.h>
#include <iostream>
#include <queue>
using namespace std;

int n, m;
char map[502][502];	// 开始保存的字符只是'.'或'X',后来还有0~7 

struct Node {	//队列结点类型
	int x, y;
	int d;	// d:0~7, 方向序号,从 EAST逆时针转到 SOUTHEAST
	Node(int x0=0, int y0=0, int d0=0) : x(x0), y(y0), d(d0) {};	// 构造函数
};
int moves[8][2] = {{1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}, {0,1}, {1,1} };
					// 位移数组moves[d]
char DirectChar[9] = "EYNVWJSQ";	// 方向序号->字符 
inline int FromCharToNo(char dch)
{	// 方向字符->序号 
	return strchr(DirectChar, dch) - DirectChar;
}

void bfs(int x, int y, int d)
{
	queue<Node> q;
	map[y][x] = d;
	q.push(Node(x, y, d));
	while (!q.empty()) {
		Node node = q.front();
		q.pop();
		for (int k = -1; k <= 1; k++) {	// 在三叉树上广搜 
			int nx, ny, nd;
			nd = (node.d + k + 8) % 8;
			nx = node.x + moves[nd][0];
			ny = node.y + moves[nd][1];
			if (ny >= 1 && ny <= n && nx >= 1 && nx <= m && map[ny][nx] == 'X') {
				map[ny][nx] = nd;
				q.push(Node(nx, ny, nd));
			}
		}
	}
}

int main()
{
	int x, y;
	int k = 0;	// case No.
	while (cin >> n >> m) {
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= m; j++)
				cin >> map[i][j];
		char dch;
		cin >> y >> x >> dch;
		bfs(x, y, FromCharToNo(dch));
		if (k++)
			cout << endl;
		for (int i = 1; i <= n; i++) {
			for (int j = 1; j <= m; j++)
				if (map[i][j] >= 0 && map[i][j] <= 7)
					cout << DirectChar[map[i][j]];
				else
					cout << map[i][j];
			cout << endl;
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/Willen_/article/details/86756454
今日推荐