UVA816(用BFS求最短路)(wf)

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.
Figure 1: An Example Walk-Through
Arrow Maz
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

题意:给你一个迷宫,给你入口和出口,让你找出从入口到出口的最短路。迷宫中没个节点所能拐的方向是已经被给定的,例如NR表示,从北边进的话,只能往右走。

这道题坑了我好长时间,由于我学习了编码风格,所以每一次在打‘,’后会不自觉地打出一个空格,而这道题的输出的‘,’后并无空格,所以WA了好几次。具体做题方法,在代码中有注释,可以看注释。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>

using namespace std;

//储存迷宫中的点,方向
struct NODE
{
    int r, c, dir;
    NODE (int r = 0, int c = 0, int dir = 0) : r(r), c(c), dir(dir) {}
};

const int maxn = 100;
const char *dirs = "NESW";
const char *turns = "FLR";
const int dr[] = {-1, 0, 1, 0};
const int dc[] = {0, 1, 0, -1};
int d[maxn][maxn][4], has_edge[maxn][maxn][4][3];
int c1, r1, r2, c2, dir, r0, c0;
NODE p[maxn][maxn][4];
string name;

//从哪里进入
int dir_id(char c)
{
    return strchr (dirs, c) - dirs;
}

//转入哪里
int turn_id(char c)
{
    return strchr (turns, c) - turns;
}

//走向下一个迷宫点
NODE walk(const NODE &u, int turn)
{
    int dir = u.dir;
    if (turn == 1) dir = (dir + 3) % 4;//如果向左转,逆时针
    if (turn == 2) dir = (dir + 1) % 4;//如果向右转,顺时针
    return NODE(u.r + dr[dir], u.c + dc[dir], dir);
}

bool inside(int r, int c)
{
    return r >=1 && r <= 9 && c >= 1 && c <= 9;//迷宫从1开始
}

//输出函数,用vector保存节点
void print_ans(NODE u)
{
    vector<NODE> nodes;
    //从最后一个节点开始往前找
    while (1) {
        nodes.push_back(u);
        if (d[u.r][u.c][u.dir] == 0) break;
        u = p[u.r][u.c][u.dir];
    }
    nodes.push_back (NODE(r0, c0, dir));

    //打印解,每行10个
    int cnt = 0;
    for (int i = (int)nodes.size() - 1; i >= 0; i--) {
        if (cnt % 10 == 0) printf (" ");
        printf (" (%d,%d)", nodes[i].r, nodes[i].c);//输出的时候不要带编码风格的空格,哭
        if (++cnt % 10 == 0) printf ("\n");
    }
    if (nodes.size() % 10 != 0) printf ("\n");
}

//BFS看最短路
void solve()
{
    queue<NODE> q;
    memset (d, -1, sizeof(d));
    NODE u(r1, c1, dir);
    d[u.r][u.c][u.dir] = 0;
    q.push(u);
    while (!q.empty()) {
        NODE u = q.front(); q.pop();
        if (u.r == r2 && u.c == c2) {
            print_ans (u);
            return;
        }
        //从前面的节点开始走,前面的节点的路径优先
        for (int i = 0; i < 3; i++) {
            NODE v = walk (u, i);
            if (has_edge[u.r][u.c][u.dir][i] && inside (v.r, v.c) && d[v.r][v.c][v.dir] < 0) {
                d[v.r][v.c][v.dir] = d[u.r][u.c][u.dir] + 1;
                p[v.r][v.c][v.dir] = u;
                q.push(v);
            }
        }
    }
    printf ("  No Solution Possible\n");
}

//输入函数
bool scan()
{
    //memset (p, 0, sizeof(p));
    memset (has_edge, 0, sizeof(has_edge));
    cin >> name;
    if (name == "END") return false;
    char s[100];
    cin >> r0 >> c0 >> s >> r2 >> c2;
    cout << name << endl;
    r1 = r0 + dr[dir_id (s[0])];
    c1 = c0 + dc[dir_id (s[0])];
    dir = dir_id (s[0]);
    int r, c;
    while (cin >> r) {
        if (r == 0) break;
        cin >> c;
        char s2[100];
        while (cin >> s2) {
            if (s2[0] == '*') break;
            int l = strlen (s2);
            for (int i = 1; i < l; i++) {
                has_edge[r][c][dir_id (s2[0])][turn_id (s2[i])] = 1;
            }
        }
    }
    return true;
}


int main()
{
    #ifndef ONLINE_JUDGE
    freopen ("in.txt", "r", stdin);
    #endif // ONLINE_JUDGE
    while (scan ()) {
        solve ();
    }
    return 0;
}
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值