The 1999 World Finals Contest included a problem based on a dice maze. At the time the problem was written, the judges were unable to discover the original source of the dice maze concept. Shortly after the contest, however, Mr. Robert Abbott, the creator of numerous mazes and an author on the subject, contacted the contest judges and identified himself as the originator of dice mazes. We regret that we did not credit Mr. Abbott for his original concept in last years problem statement. But we are happy to report that Mr. Abbott has offered his expertise to this years contest with his original and unpublished walk-through arrow mazes.
As are most mazes, a walk-through arrow maze is traversed by moving from intersection to intersection until the goal intersection is reached. As each intersection is approached from a given direction, a sign near the entry to the intersection indicates in which directions the intersection can be exited. These directions are always left, forward or right, or any combination of these.
Figure 1 illustrates a walk-through arrow maze. The intersections are identified as (row, column) pairs, with the upper left being (1,1). The Entrance intersection for Figure 1 is (3,1), and the Goal intersection is (3,3). You begin the maze by moving north from (3,1). As you walk from (3,1) to (2,1), the sign at (2,1) indicates that as you approach (2,1) from the south (traveling north) you may continue to go only forward. Continuing forward takes you toward (1,1). The sign at (1,1) as you approach from the south indicates that you may exit (1,1) only by making a right. This turns you to the east now walking from (1,1) toward (1,2). So far there have been no choices to be made. This is also the case as you continue to move from (1,2) to (2,2) to (2,3) to (1,3). Now, however, as you move west from (1,3) toward (1,2), you have the option of continuing straight or turning left. Continuing straight would take you on toward (1,1), while turning left would take you south to (2,2). The actual (unique) solution to this maze is the following sequence of intersections: (3,1) (2,1) (1,1) (1,2) (2,2) (2,3) (1,3) (1,2) (1,1) (2,1) (2,2) (1,2) (1,3) (2,3) (3,3).
You must write a program to solve valid walk-through arrow mazes. Solving a maze means (if possible) finding a route through the maze that leaves the Entrance in the prescribed direction, and ends in the Goal. This route should not be longer than necessary, of course.
Input
The input file will consist of one or more arrow mazes. The first line of each maze description contains the name of the maze, which is an alphanumeric string of no more than 20 characters. The next line contains, in the following order, the starting row, the starting column, the starting direction, the goal row, and finally the goal column. All are delimited by a single space. The maximum dimensions of a maze for this problem are 9 by 9, so all row and column numbers are single digits from 1 to 9. The starting direction is one of the characters N, S, E or W, indicating north, south, east and west, respectively.
All remaining input lines for a maze have this format: two integers, one or more groups of characters, and a sentinel asterisk, again all delimited by a single space. The integers represent the row and column, respectively, of a maze intersection. Each character group represents a sign at that intersection. The first character in the group is ‘N’, ‘S’, ‘E’ or ‘W’ to indicate in what direction of travel the sign would be seen. For example, ‘S’ indicates that this is the sign that is seen when travelling south. (This is the sign posted at the north entrance to the intersection.) Following this first direction character are one to three arrow characters. These can be ‘L’, ‘F’ or ‘R’ indicating left, forward, and right, respectively.
The list of intersections is concluded by a line containing a single zero in the first column. The next line of the input starts the next maze, and so on. The end of input is the word ‘END’ on a single line by itself.
Output
For each maze, the output file should contain a line with the name of the maze, followed by one or more lines with either a solution to the maze or the phrase ‘No Solution Possible’. Maze names should start in column 1, and all other lines should start in column 3, i.e., indented two spaces. Solutions should be output as a list of intersections in the format (R,C) in the order they are visited from the start to the goal, should be delimited by a single space, and all but the last line of the solution should contain exactly 10 intersections.
Note: Figure 2: Robert Abbott’s Atlanta Maze Robert Abbotts walk-through arrow mazes are actually intended for large-scale construction, not paper. Although his mazes are unpublished, some of them have actually been built. One of these is on display at an Atlanta museum. Others have been constructed by the American Maze Company over the past two summers. As their name suggests these mazes are intended to be walked through.
For the adventurous, Figure 2 a graphic of Robert Abbotts Atlanta maze. Solving it is quite difficult, even when you have an overview of the entire maze. Imagine trying to solve this by actually walking through the maze and only seeing one sign at a time! Robert Abbott himself indicated that the maze is too complex and most people give up before finishing. Among the people that did not give up was Donald Knuth: it took him about thirty minutes to solve the maze.
The first maze in the following sample input is the maze in Figure 1.
Sample Input
SAMPLE
3 1 N 3 3
1 1 WL NR *
1 2 WLF NR ER *
1 3 NL ER *
2 1 SL WR NF *
2 2 SL WF ELF *
2 3 SFR EL *
0
NOSOLUTION
3 1 N 3 2
1 1 WL NR *
1 2 NL ER *
2 1 SL WR NFR *
2 2 SR EL *
0
END
Sample Output
SAMPLE
(3,1) (2,1) (1,1) (1,2) (2,2) (2,3) (1,3) (1,2) (1,1) (2,1)
(2,2) (1,2) (1,3) (2,3) (3,3)
NOSOLUTION
No Solution Possible
题目类型:简单BFS
算法分析:使用一个三元组(x,y,dir)表示走到每个点的状态,再使用一个par[x][y][dir]记录路径
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 |
/************************************************** filename :g.cpp author :maksyuki created time :2018/5/31 22:19:28 last modified :2018/5/31 23:57:06 file location :C:\Users\abcd\Desktop\TheEternalPoet ***************************************************/ #pragma comment(linker, "/STACK:102400000,102400000") #include <set> #include <bitset> #include <list> #include <map> #include <stack> #include <queue> #include <deque> #include <string> #include <vector> #include <ios> #include <iostream> #include <fstream> #include <sstream> #include <iomanip> #include <algorithm> #include <utility> #include <complex> #include <numeric> #include <functional> #include <cmath> #include <ctime> #include <climits> #include <cstdarg> #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <cassert> using namespace std; #define CFF freopen ("in", "r", stdin) #define CFO freopen ("out", "w", stdout) #define CPPFF ifstream cin ("in") #define CPPFO ofstream cout ("out") #define DB(ccc) cout << #ccc << " = " << ccc << endl #define DBT printf("time used: %.2lfs\n", (double) clock() / CLOCKS_PER_SEC) #define PB push_back #define MP(A, B) make_pair(A, B) typedef long long LL; typedef unsigned long long ULL; typedef double DB; typedef pair <int, int> PII; typedef pair <int, bool> PIB; const int INF = 0x7F7F7F7F; const int MOD = 1e9 + 7; const double EPS = 1e-10; const double PI = 2 * acos (0.0); const int maxn = 16; int s_row, s_col, e_row, e_col; string s_dir; map<char, int> dict; vector<int> dx[maxn][maxn][4]; vector<int> dy[maxn][maxn][4]; vector<int> ddir[maxn][maxn][4]; bool vis[maxn][maxn][4]; struct node { int x, y, dir; node () {} node (int xx, int yy, int dd): x(xx), y(yy), dir(dd) {} }; node par[maxn][maxn][4]; void init() { for(int i = 0; i < maxn; i++) for(int j = 0; j < maxn; j++) for(int k = 0; k < 4; k++) { dx[i][j][k].clear(); dy[i][j][k].clear(); ddir[i][j][k].clear(); } memset(par, 0, sizeof(par)); memset(vis, false, sizeof(vis)); } bool In(const int x, const int y) { if(x >= 1 && x <= 9 && y >= 1 && y <= 9) return true; return false; } bool bfs(int x, int y, char c) { queue<node> qu; int tmp_dir = dict[c]; qu.push(node(x, y, tmp_dir)); vis[x][y][tmp_dir] = true; while(!qu.empty()) { node tmp = qu.front(); qu.pop(); if(tmp.x == e_row && tmp.y == e_col) { return true; } int tmplen = dx[tmp.x][tmp.y][tmp.dir].size(); for(int i = 0; i < tmplen; i++) { int xx = tmp.x + dx[tmp.x][tmp.y][tmp.dir][i]; int yy = tmp.y + dy[tmp.x][tmp.y][tmp.dir][i]; int dd = ddir[tmp.x][tmp.y][tmp.dir][i]; if(In(xx, yy) && !vis[xx][yy][dd]) { //cout << "x: " << xx << " y: " << yy << " dir: " << dd << endl; qu.push(node(xx, yy, dd)); vis[xx][yy][dd] = true; par[xx][yy][dd].x = tmp.x; par[xx][yy][dd].y = tmp.y; par[xx][yy][dd].dir = tmp.dir; } } } return false; } const int ddx[] = {0, 1, 0, -1}; const int ddy[] = {-1, 0, 1, 0}; void Build(const string &s, const int x, const int y) { int tmp_dir; for(int i = 0; s[i]; i++) { if(!i) { tmp_dir = dict[s[i]]; } else { int tt_dir; if(s[i] == 'L') tt_dir = (tmp_dir + 1) % 4; else if(s[i] == 'R') tt_dir = (tmp_dir + 3) % 4; else tt_dir = tmp_dir; dx[x][y][tmp_dir].emplace_back(ddx[tt_dir]); dy[x][y][tmp_dir].emplace_back(ddy[tt_dir]); ddir[x][y][tmp_dir].emplace_back(tt_dir); } } } int main() { #ifdef LOCAL CFF; //CFO; #endif dict['W'] = 0, dict['S'] = 1; dict['E'] = 2, dict['N'] = 3; string s; while(cin >> s) { if(s == "END") break; init(); cin >> s_row >> s_col >> s_dir >> e_row >> e_col; int p_row, p_col; while(cin >> p_row) { if(!p_row) break; cin >> p_col; string ss; while(cin >> ss) { if(ss == "*") break; Build(ss, p_row, p_col); } } int ss_dir = dict[s_dir[0]]; dx[s_row][s_col][ss_dir].emplace_back(ddx[ss_dir]); dy[s_row][s_col][ss_dir].emplace_back(ddy[ss_dir]); ddir[s_row][s_col][ss_dir].emplace_back(ss_dir); cout << s << endl; if(bfs(s_row, s_col, s_dir[0])) { vector<node> ans; int pp_x = 0, pp_y = 0, pp_dir = 0; for(int i = 0; i < 4; i++) if(par[e_row][e_col][i].x) { pp_x = par[e_row][e_col][i].x; pp_y = par[e_row][e_col][i].y; pp_dir = par[e_row][e_col][i].dir; ans.emplace_back(node(e_row, e_col, i)); break; } int ttx, tty, ttdir; do { ans.emplace_back(node(pp_x, pp_y, pp_dir)); ttx = pp_x, tty = pp_y; ttdir = pp_dir; pp_x = par[ttx][tty][ttdir].x; pp_y = par[ttx][tty][ttdir].y; pp_dir = par[ttx][tty][ttdir].dir; }while(pp_x && pp_y); int anslen = ans.size(); bool is_first = true; int out_cnt = 0; for(int i = anslen - 1; i >= 0; i--) { if(is_first) { is_first = false; cout << " "; } cout << " (" << ans[i].x << "," << ans[i].y << ")"; out_cnt++; if(out_cnt >= 10) { out_cnt = 0; is_first = true; cout << endl; } } if(!is_first) cout << endl; } else cout << " No Solution Possible" << endl; } return 0; } |
- « 上一篇:uva1103
- uva10305:下一篇 »