UVa 816

题意

最多有9*9个节点的迷宫, 这个迷宫特殊的是, 每个节点可走的方向是特定的. 比如 1 2 WLF * 这个指令的意思是若朝向西来到点(1,2), 可以选择左转或直走
uva816

思路

BFS
一开始用数组做的模拟, 上交RE了, 不知道原因是什么
学习紫书写法, 利用队列和结构体

AC代码

#include <iostream>
#include <queue>
#include <cstdio>
#include <cstring>
#include <vector>

using namespace std;

char name[25], str[10];
int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};

//借助 strchr() 函数可以查找字符串s中首次出现字符c的位置这一功能将下列字母标序号
const char* ds = "NESW";  //标号为0-3 北东南西
const char* ts = "FLR";  //标号为0-2 直左右
int ds_id( char c ){ return strchr(ds, c) - ds; }
int ts_id( char c ){ return strchr(ts, c) - ts; }
int x1, y1, x2, y2, t;
char tt;

struct Node{
    int x, y, a;
    Node(int x = 0, int y = 0, int a = 0):x(x),y(y),a(a){}
};

bool judge[10][10][5][5], pla[10][10];
int vis[10][10][5];
Node pre[10][10][5];
void PRINT( Node u ){
    vector<Node> n;
    for(;;){
        n.push_back(u);
        if( vis[u.x][u.y][u.a] == 0 )   break;
        u = pre[u.x][u.y][u.a];
    }
    n.push_back(Node(x1,y1,t));
    int cnt = 0;
    for( int i = n.size()-1; i >= 0; i-- ){
        cnt++;
        if( cnt % 10 == 1 )     printf(" ");
        printf(" (%d,%d)",n[i].x, n[i].y);
        if( cnt % 10 == 0 || i == 0 )   putchar('
');
    }
}
Node getv( Node u, int i ){  //i=0:直走,方向不变,  i=1:左转,  i=2:右转
    int a = u.a;
    if( i == 1 )   a = u.a-1 < 0 ? 3 : u.a-1;
    else if( i == 2 )   a = u.a+1 > 3 ? 0 : u.a+1;
    return Node(u.x+dir[a][0], u.y+dir[a][1], a );
}

void bfs()
{
    queue<Node> q;
    Node u(x1 + dir[t][0], y1 + dir[t][1], t);
    vis[u.x][u.y][u.a] = 0;
    q.push(u);
    while( !q.empty() ){
        Node u = q.front();
        q.pop();
        if( u.x == x2 && u.y == y2 ){
            PRINT(u);
            return;
        }
        for( int i = 0; i < 3; i++ ){
            Node v = getv(u, i);
            if( judge[u.x][u.y][u.a][i] && vis[v.x][v.y][v.a] < 0 && pla[v.x][v.y] ){
                vis[v.x][v.y][v.a] = vis[u.x][u.y][u.a] + 1;
                pre[v.x][v.y][v.a] = u;
                q.push(v);
            }
        }
    }
    printf("  No Solution Possible
");
    return;
}

void readin()
{
    scanf("%d%d %c %d%d",&x1, &y1, &tt, &x2, &y2);
    pla[x1][y1] = true;
    pla[x2][y2] = true;
    t = ds_id(tt);
    int aa, bb;
    while( scanf("%d",&aa) && aa){
        scanf("%d",&bb);
        pla[aa][bb] = true;
        while( scanf("%s",str) && strcmp(str, "*") != 0 ){
            int len = strlen(str);
            for( int i = 1; i < len; i++ )
                judge[aa][bb][ds_id(str[0])][ts_id(str[i])] = true;
        }
    }
}

void solve()
{
    memset(judge, 0, sizeof(judge));
    memset(vis, -1, sizeof(vis));
    memset(pla, 0, sizeof(pla));
    readin();
    printf("%s
",name);
    bfs();
}

int main()
{
    while( ~scanf("%s",name) && strcmp(name, "END") != 0 )
        solve();
    return 0;
}

RE代码

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 10000;
char name[25], str[10];
int dir[4][2] = {{-1,0},{0,1},{1,0},{0,-1}};
int pre[maxn];
//借助 strchr() 函数可以查找字符串s中首次出现字符c的位置这一功能将下列字母标序号
const char* ds = "NESW";  //标号为0-3 北东南西
const char* ts = "FLR";  //标号为0-2 直左右
int ds_id( char c ){ return strchr(ds, c) - ds; }
int ts_id( char c ){ return strchr(ts, c) - ts; }
int x1, y1, x2, y2, t;
char tt;
bool flag;

struct Node{ int x, y, a; };
Node p[maxn];
bool judge[10][10][5][5], vis[10][10][5], pla[10][10];

int cnt = 0;
void PRINT( int a ){
    int t = pre[a];
    if( t != 0 )
        PRINT(t);
    else{
        printf(" (%d,%d)",x1, y1);
        printf(" (%d,%d)",p[0].x, p[0].y);
        cnt += 2;
    }
    printf(" (%d,%d)",p[a].x, p[a].y);
    cnt += 1;
    if( cnt % 10 == 0 ) putchar('
');
}

void bfs()
{
    int head = 0, tail = 1, m, n, o, mm, nn, oo;
    p[0].x = x1 + dir[t][0], p[0].y = y1 + dir[t][1], p[0].a = t;
    pre[0] = -1;
    while( head < tail ){
        m = p[head].x, n = p[head].y, o = p[head].a;
        //cout << m << ' ' << n << ' ' << o << endl;
        if( m == x2 && n == y2 ){
            PRINT(head);
            flag = true;
            return;
        }
        for( int i = 0; i < 3; i++ ){
            if( judge[m][n][o][i] ){  //i=0:直走,方向不变,  i=1:左转,  i=2:右转
                if( i == 0 )    oo = o;
                else if( i == 1 )   oo = o-1 < 0 ? 3 : o-1;
                else if( i == 2 )   oo = o+1 > 3 ? 0 : o+1;
                mm = m + dir[oo][0];
                nn = n + dir[oo][1];
            }
            if( !vis[mm][nn][oo] && pla[mm][nn] ){
                //cout << mm << ' ' << nn << ' ' << endl;
                vis[mm][nn][oo] = true;
                p[tail].x = mm;
                p[tail].y = nn;
                p[tail].a = oo;
                pre[tail] = head;
                tail++;
            }
        }
        head++;
    }
    return;
}

void readin()
{
    scanf("%d%d %c %d%d",&x1, &y1, &tt, &x2, &y2);
    pla[x1][y1] = true;
    pla[x2][y2] = true;
    t = ds_id(tt);
    int aa, bb;
    while( scanf("%d",&aa) && aa){
        scanf("%d",&bb);
        pla[aa][bb] = true;
        while( scanf("%s",str) && strcmp(str, "*") != 0 ){
            int len = strlen(str);
            for( int i = 1; i < len; i++ )
                judge[aa][bb][ds_id(str[0])][ts_id(str[i])] = true;
        }
    }
}

void solve()
{
    memset(judge, 0, sizeof(judge));
    memset(vis, 0, sizeof(vis));
    memset(pla, 0, sizeof(pla));
    flag = false;
    readin();
    printf("%s
",name);
    bfs();
    if( !flag ) printf(" No Solution Possible");
    putchar('
');
}

int main()
{
    while( ~scanf("%s",name) && strcmp(name, "END") != 0 )
        solve();
    return 0;
}
原文地址:https://www.cnblogs.com/JinxiSui/p/9740596.html