Johnny likes solving puzzles. He especially likes drawing and solving mazes. However, solving
a maze he has drawn himself is too easy for him.
Since his computer is his best friend, he figures that he needs a program drawing the mazes
for him. So he starts thinking about an algorithm performing this difficult task for him and he
comes up with `Johnny's Simple Algorithm.'
You start with a
M×N grid, where M is the number of rows and N is the number of columns of
the grid. Initially, no two cells of the grid are connected to each other, so every cell is surrounded
by walls on all four sides. The walls consist of an underscore (`_') for a horizontal wall, and a
vertical bar (`|') for a vertical one. For example, if M = 3 and N = 4, the grid looks like this:
_ _ _ _
|_|_|_|_|
|_|_|_|_|
|_|_|_|_|
Every cell of the grid has unique coordinates (p, q). The lower left corner in the example is (1, 1),
the upper right corner is (3, 4).
After choosing the dimensions of the maze, you choose a starting cell. From now on you keep
track of a list of pending cells, which initially contains only one cell (the starting cell), and you
repeat the following steps:
- If the list is empty, you stop. The maze is ready.
- Else, you consider the most recently added cell in the list (call this cell AC). If this cell
(at the end of the list) has no unvisited neighbor cells then you remove this cell from the
list. Every cell has at most 4 neighbor cells: on the right, left, above and below. A cell is
unvisited if it has never been added to the list.
- If AC has at least one unvisited neighbor cell, you choose one of the unvisited neighbor cells
(call this cell NC), remove the wall between AC and NC and add NC to the end of the list.
Johnny makes a nice little program using this algorithm and it works fine, but Johnny is not
completely satisfied with the results. He is a demanding little boy and in his opinion the so-called
branching factor of the maze is too low, i.e. the generated mazes contain very long paths and too
few crossings. Therefore, the mazes are still too easy to solve for him.
A little trick can be applied to Johnny's Simple Algorithm, giving much better results. Johnny
does not know it, but you will, since it will be explained below!
The idea behind the trick is to sometimes change the order of the cells in the list. This avoids
long paths and results in more branches. Changing the order of the cells in the list is done by
`flipping' part of the list. A flip can be specified by giving the position of a cell in the list (where
the first cell has position 1) and consists of reversing the sub-list starting at the specified cell and
ending with the last cell in the list.
For example, if the list consists of the following cells:
(1, 1)(1, 2)(2, 2)(3, 2)(3, 3)
then a flip with starting cell number 2 results in:
(1, 1)(3, 3)(3, 2)(2, 2)(1, 2)
Now, we will reveal `Johnny's Advanced Algorithm.'
The algorithm is pretty much the same as `Johnny's Simple Algorithm,' only sometimes part of
the list is flipped. The steps you repeat after choosing the dimensions of the maze, choosing the
starting cell and adding this cell to the list are:
- If the list of cells is empty, you stop. The maze is ready.
- Else you consider the last cell in the list. If this cell has no unvisited neighbor cells, then
you remove this cell from the list.
- Otherwise, you read a command. If this command is:
- `F n'
- you flip the list, starting at position n.
- `U'
- you go up: you remove the wall between the last cell in the list and the cell above it.
The cell above the last cell in the list is added to the list.
- `D'
- you go down.
- `L'
- you go left.
- `R'
- you go right.
Since you are taking part in a programming contest, we ask you to write a program generating
nice mazes for Johnny, using `Johnny's Advanced Algorithm,' to make him happy again. The
maximum size of a maze is 39×39.
The first line of the input contains the number of test cases. The input for every test case is
divided into three parts:
- The first line contains two integer values M and N, specifying the dimensions of the maze:
the number of rows M followed by the number of columns N.
- The second line contains the coordinates of the starting point (again, row followed by column).
- The next lines each contain a command. A command is one of the upper case characters
`F', `U', `D', `L' and `R', appearing at the start of a line. An `F'
character is followed by a space and an integer (the starting position of the flip.)
The input for each test case contains exactly the number of commands needed for that maze.
The resulting mazes should be printed using spaces (`'), underscores (`_'), vertical bars (`|')
and end-of-line characters. No unnecessary whitespace should be printed. The mazes should be
followed by one blank line.
2
3 3
1 1
U
U
R
D
D
R
U
U
3 4
2 1
R
U
L
F 2
R
U
R
D
D
F 4
D
L
L
_ _ _
| | |
| | | |
|_|_ _|
_ _ _ _
|_ | |
|_ _ | |
|_ _ _|_|
Testsetter: Joachim Wulff (Little Joey)
Special thanks: Ruben Spaans
題目描述:
模擬一個 stack,按照指令將 stack 頂部的點走到下一個點去,當頂部的四周都沒辦法走時,
則將 stack pop,而指令中有一個將 stack 上層反轉放回。
題目一定給定剛好的指令,使得迷宮建造完全。
如何反轉,請參照題目的例子。
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
using namespace std;
int g[40][40][4];
int visited[40][40];
int dx[] = {1, 0, 0,-1};//UP, left, right,DOWN
int dy[] = {0, -1, 1,0};
int n, m;
stack<int> X, Y;
int remove() {
if(X.empty())
return 0;
int i, tx, ty;
for(i = 0; i < 4; i++) {
tx = X.top()+dx[i];
ty = Y.top()+dy[i];
if(tx < 0 || ty < 0 || tx >= n || ty >= m)
continue;
if(visited[tx][ty] == 0)
return 0;
}
return 1;
}
void print() {
int i, j;
for(j = 0; j < m; j++) {
putchar(' ');
putchar('_');
}
puts("");
for(i = n-1; i >= 0; i--) {
putchar('|');
for(j = 0; j < m; j++) {
//printf("(%d,%d,%d,%d)", g[i][j][0], g[i][j][1], g[i][j][2], g[i][j][3]);
putchar(g[i][j][3] ? '_' : ' ');
putchar(g[i][j][2] ? '|' : ' ');
}
puts("");
}
}
int main() {
int testcase;
int sx, sy;
int i, j, k, x, y;
scanf("%d", &testcase);
while(testcase--) {
scanf("%d %d", &n, &m);
scanf("%d %d", &sx, &sy);
sx--, sy--;
memset(visited, 0, sizeof(visited));
X.push(sx), Y.push(sy);
for(i = 0; i < n; i++) {
for(j = 0; j < m; j++) {
g[i][j][0] = g[i][j][1] = g[i][j][2] = g[i][j][3] = 1;//wall
}
}
visited[sx][sy] = 1;
char cmd[10];
int dir = 0;
//The input for each test case contains exactly the number of commands needed for that maze.
while(!X.empty()) {
scanf("%s", cmd);
if(cmd[0] == 'F') {
scanf("%d", &x);
queue<int> tx, ty;
int cnt = X.size()-x+1;
for(i = 0; i < cnt; i++) {
tx.push(X.top());
ty.push(Y.top());
X.pop(), Y.pop();
}
while(!tx.empty()) {
X.push(tx.front());
Y.push(ty.front());
tx.pop(), ty.pop();
}
} else {
if(cmd[0] == 'U') dir = 0;
if(cmd[0] == 'D') dir = 3;
if(cmd[0] == 'L') dir = 1;
if(cmd[0] == 'R') dir = 2;
int tx, ty;
tx = X.top()+dx[dir];
ty = Y.top()+dy[dir];
//printf("%d %d %d\n", tx, ty, dir);
if(tx >= 0 && tx < n && ty >= 0 && ty < m) {
if(visited[tx][ty] == 0) {
g[X.top()][Y.top()][dir] = 0;
g[tx][ty][3-dir] = 0;
X.push(tx), Y.push(ty);
visited[tx][ty] = 1;
}
}
}
while(remove()) {X.pop(), Y.pop();}
}
print();
puts("");
}
return 0;
}
文章定位: