您的位置:首页 > 其它

【算法竞赛入门经典】6.4.2用BFS求最短路 例题6-14 UVa816

2018-02-02 17:21 501 查看

【算法竞赛入门经典】6.4.2用BFS求最短路 例题6-14 UVa816

算法竞赛入门经典642用BFS求最短路 例题6-14 UVa816
例题UVa816

BFS

本题储存结构

思路

样例实现代码

例题UVa816

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 inter section 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

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

BFS,其英文全称是Breadth First Search。 BFS并不使用经验法则算法。从算法的观点,所有因为展开节点而得到的子节点都会被加进一个先进先出的队列中。

之所以称之为宽度优先算法,是因为算法自始至终一直通过已找到和未找到顶点之间的边界向外扩展,就是说,算法首先搜索和s距离为k的所有顶点,然后再去搜索和S距离为k+l的其他顶点。

本题储存结构

实际上,本题需要记录的节点信息有:行、列、进入节点的朝向、可以行进的方向。此处使用一个Int数组AbleToTurn来记录某一行某一列的节点当面朝某方向进来时能否向某处转向。

此外,还需要记录节点走过步数,用Dis数组记录某个点当以某个方向进入时距离起点的最短距离。这在之后用于判断是否是最短路【第一次被赋值是最短的,其他的要么和他距离一样要不是赋值比它大,因为使用的是BFS】。

typedef struct List
{
int data;
struct List *next;
};


思路

从起点开始进行BFS,求得沿途节点以某个方向进入时距离起点的最短路程并记录其父节点,直到找到终点为止。由BFS可知,在不考虑多解的情况下,这一定是最短的。

样例实现代码

TIP:本代码仅仅针对样例,固定了起点的方向,看上去简化,实际上不能提交。

#include<iostream>
#include<queue>
#include<vector>
#include<string>
#define MAX 3
using namespace std;
int s_row, s_col, s_dir, d_row, d_col;
char s_dir_c;
int AbleToTurn[MAX+1][MAX+1][4][3];
int Dis[MAX + 1][MAX + 1][4];
string s;
typedef struct Node {
int row;
int col;
int dir;
Node(int r=0,int c=0,int d=-1):row(r),col(c),dir(d){}
}Node;
Node parents[MAX + 1][MAX + 1][MAX + 1];
const char *dir = "NESW";
const char
bc87
*turn = "FLR";
const int nextrow[] = { -1,0,1,0 };
const int nextcol[] = { 0,1,0,-1 };
int getdirID(char a) {
return strchr(dir, a) - dir;
}
int getturnID(char a) {
return strchr(turn, a) - turn;
}
bool readdata() {
int setrow, setcol;
char first, other;
cin >> s_row;
if (s_row == 0)
return false;
cin >> s_col >> s_dir_c >> d_row >> d_col;
s_dir = getdirID(s_dir_c);
memset(AbleToTurn, 0, sizeof(AbleToTurn));
while (1) {
cin >> setrow;
if (setrow == 0)
break;
cin >> setcol;
while (cin >> s) {
if (s[0] == '*')
break;
first = s[0];
for (int i = 1; i < s.length(); i++) {
AbleToTurn[setrow][setcol][getdirID(first)][getturnID(s[i])] = 1;
}
}
}
}
Node walk(Node u, int i) {
int dir = u.dir;
if (i == 1)
dir = (dir + 3) % 4;
if (i == 2)
dir = (dir + 1) % 4;
return Node(u.row + nextrow[dir], u.col + nextcol[dir], dir);
}
void PrintAns(Node fin) {
vector<Node>ans;
while (1) {
ans.push_back(fin);
if (fin.row == s_row && fin.col == s_col)
break;
fin = parents[fin.row][fin.col][fin.dir];
}
for (int i = ans.size() - 1; i >= 0; i--)
cout << "( " << ans[i].row << "," << ans[i].col << " )" << " ";
cout << endl;
}
void solve() {
Node u = Node(s_row, s_col, s_dir);
Node next;
memset(Dis, -1, sizeof(Dis));
queue<Node>q;
Dis[u.row][u.col][u.row] = 0;
next = walk(u, 0);
parents[next.row][next.col][next.dir] = u;
q.push(next);
while (!q.empty()) {
u = q.front();
q.pop();
for (int i = 0; i < 3; i++) {
if (AbleToTurn[u.row][u.col][u.dir][i] == 1) {
next = walk(u, i);
if (Dis[next.row][next.col][next.dir] < 0) {
Dis[next.row][next.col][next.dir] = Dis[u.row][u.col][u.dir] + 1;
parents[next.row][next.col][next.dir] = u;
q.push(next);
if (next.row == d_row && next.col == d_col) {
PrintAns(next);
return;
}
}
}
}
}
cout << "No Solution" << endl;
}
int main() {
while (readdata()) {
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐