例题6-14 Abbott's Revenge Uva816

来源:互联网 发布:耳机线材靠谱的淘宝店 编辑:程序博客网 时间:2024/06/05 07:52

题目连接:https://vjudge.net/problem/UVA-816

题意:有一个 9 * 9 的交叉点的迷宫。 输入起点, 离开起点时的朝向和终点, 求最短路(多解时任意一个输出即可)。进入一个交叉点的方向(用NEWS表示不同方向)不同时, 允许出去的方向也不相同。 例如:1 2 WLF NR ER * 表示如果 进去时朝W(左), 可以 左转(L)或直行(F), 如果 朝N只能右转(R) 如果朝E也只能右转。* 表示这个点的描述结束啦!

    输入有: 起点的坐标, 朝向, 终点的坐标。然后是各个坐标,和各个坐标点的情况(进去方向和可以出去的方向) 以*号表示各个坐标点描述的结束。

题目分析:本题和普通的迷宫在本质上是一样的, 但是由于“朝向”也起了关键的作用, 所以需要一个三元组(r,c, dir)表示位于(r, c)面朝dir 的状态。 假设入口位置为(r0,c0)朝向为dir , 则初始状态并不是(r0, c0, dir), 而是(r1, c1, dir)因为开始时他别无选择, 只有一个规定的方向。 其中, (r1, c1)是沿着方向dir走一步之后的坐标, dir刚好是他进入该点时的朝向。    此处用d[r][c][dir]表示初始状态到(r, c, dir)的最短路长度, 并且用 p[r][c][dir]保存了状态(r, c, dir)在BFS树中的父结点。

思路:简单BFS应用,但是细节很多,格式神烦。

Code:

#include <bits/stdc++.h>using namespace std;const int AX = 20;int d[AX][AX][4];int has_edge[AX][AX][AX][AX];int start_r , start_c , end_r , end_c;int s_x , s_y ,s_dir;char start_dir[5]  ;string name;struct Node{int x , y ;int dir;Node(){};Node( int x_ , int y_ , int dir_ ) { x = x_ ; y = y_; dir = dir_; }}start;Node p[AX][AX][4];const char* dirs = "NESW";const char* turns = "FLR";int dir_id(char ch) { return strchr(dirs,ch)-dirs; }int turns_id(char ch) { return strchr(turns,ch)-turns; }const int dr[] = { -1, 0, 1, 0 };const int dc[] = {  0, 1, 0,-1 };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.x + dr[dir] , u.y + dc[dir] , dir );}bool inside( int x , int y ){if( x >= 1 && x <= 9 && y >= 1 && y <= 9 ){return true;}else return false;}void print( Node u ){ std::vector<Node> v;while( true ){v.push_back(u);if( !d[u.x][u.y][u.dir] )  break;u = p[u.x][u.y][u.dir];}int cnt = 0;cout << name << endl;v.push_back(Node(s_x,s_y,s_dir));for( int i = v.size() - 1 ; i >= 0 ; i-- ){if( cnt % 10 == 0 ) cout << " " ;cout << " (" << v[i].x << ',' << v[i].y << ")";if( ++cnt % 10 == 0 ) cout << endl;}if( v.size() % 10 != 0 ) cout << endl;}void BFS( ){queue<Node>q; memset(d,-1,sizeof(d));d[start.x][start.y][start.dir] = 0;q.push(start);while( !q.empty() ){Node u = q.front();q.pop();if( u.x == end_r && u.y == end_c ) { print( u ); return; }for( int i = 0 ; i < 3 ; i++ ){Node v = walk( u , i );if( has_edge[u.x][u.y][u.dir][i] && inside(v.x,v.y) && d[v.x][v.y][v.dir] < 0 ){p[v.x][v.y][v.dir] = u;d[v.x][v.y][v.dir] = d[u.x][u.y][u.dir] + 1;q.push(v);}}}cout << name << endl;cout << "  No Solution Possible" << endl;}int main(){ios_base::sync_with_stdio(false); cin.tie(0);//freopen("x.txt","r",stdin);while( cin >> name ){memset(has_edge,0,sizeof(has_edge));if( name == "END" ){break;}cin >> start_r >> start_c >> start_dir >> end_r >> end_c;s_x = start_r ; s_y = start_c;if( start_dir[0] == 'N' ) start_r--;else if( start_dir[0] == 'S' ) start_r++;else if( start_dir[0] == 'E' ) start_c++;else start_c --;start.x = start_r; start.y = start_c ; start.dir = dir_id(start_dir[0]); s_dir = dir_id(start_dir[0]);int x , y ;while( cin >> x ){if( x == 0 ) break;cin >> y ;string s;while( cin >> s ){if( s[0] == '*' ) break;int len = s.size();int id = dir_id(s[0]);for( int i = 1; i < len ; i++ ){has_edge[x][y][id][turns_id(s[i])] = 1;}}}BFS();}return 0;}