UVA 816 Abbott's Revenge(2000 Final)

题意:

有一个最多包涵9*9个交叉点的迷宫。输入起点,离开起点时的朝向和终点,求一条最短路。

思路:

这个迷宫的特殊之处在于:进入一个交叉点的方向不同,那么允许出去的方式也不同。而且朝向起到了关键的作用。所以要用一个三元组(r,c,dir)表示位于(r,c)面朝dir这个状态。由于初始时第一步怎么走是确定的,因此要从X1,Y1开始BFS,而不是X0,Y0。由于要打印路径,因此要记录前驱。

#include <queue>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;

struct node{
    int x,y;
    int w;
    void init(int nx, int ny, int nw){
        x = nx;
        y = ny;
        w = nw;
    }
}p[10][10][4];

int X0,Y0,X1,Y1,W1,SX,SY;

int dir[4][3][2] ={{-1, 0, 0, -1, 0, 1},
                   {0, 1, -1, 0, 1, 0},
                   {1, 0, 0, 1, 0, -1},
                   {0, -1, 1, 0, -1, 0}
                  };///移动数组 

int map[10][10][4],vis[10][10][4];
int id(char c){
    if(c == 'N' || c == 'F')    return 0;
    else if(c == 'E' || c == 'L')   return 1;
    else if(c == 'S' || c == 'R')   return 2;
    else return 3;
}

void print(int x, int y, int w);
int bfs(int x, int y, int w){
    queue <node> q;
    while(!q.empty())
        q.pop();
    node a,b;
    a.init(x, y, w);
    vis[a.x][a.y][a.w] = 0;
    q.push(a);
    while(!q.empty()){
        a = q.front();
        q.pop();
        if(a.x == SX && a.y == SY){
            print(a.x, a.y, a.w);
            return 1;
        }
        int xx, yy, ww;
        for(int i=0; i<3; i++){
            xx = a.x, yy = a.y, ww = a.w;
            xx += dir[a.w][i][0];
            yy += dir[a.w][i][1];
            if(i == 1)  ww = (ww + 3) % 4;///用数字间的关系模拟向左转
            else if(i == 2) ww = (ww + 1) % 4;
            b.init(xx, yy, ww);
            if((map[a.x][a.y][a.w]) & (1 << i)){///a & pow(2,n)检测a的第n位是否为1,是返回正数,否则返回假
                if(xx < 1 || xx > 9 || yy < 1 || yy > 9)
                    continue;
                if(vis[xx][yy][ww] >= 0)
                    continue;
                vis[xx][yy][ww] = vis[a.x][a.y][a.w] + 1;
                p[xx][yy][ww] = a;///记录前驱即父亲节点以打印路径
                q.push(b);
            }
        }
    }
    return 0;
}

void print(int x, int y, int w){///用动态数组打印路径
    vector <node> v;
    node a,b;
    a.init(x, y, w);
    v.push_back(a);
    while(vis[a.x][a.y][a.w]){
        a = p[a.x][a.y][a.w];
        v.push_back(a);
    }
    a.init(X0, Y0, W1);
    v.push_back(a);
    int cnt = 0;
    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)   cout << endl;
}

int main(){
//    freopen("in.txt", "r", stdin);
    char str[30];
    while(cin >> str){
        if(!strcmp(str, "END")) break;
        cout << str << endl;
        memset(map, 0, sizeof(map));
        memset(vis, -1, sizeof(vis));
        char c;
        cin >> X0 >> Y0 >> c >> SX >> SY;
        W1 = id(c);
        X1 = X0 + dir[W1][0][0];
        Y1 = Y0 + dir[W1][0][1];
        int xx,yy;
        while(cin >> xx && xx){
            cin >> yy;
            gets(str);
            int i = 1, j = id(str[1]);
            while(str[i++] != '*'){
                if(str[i] == ' '){
                    j = id(str[++i]);
                    continue;
                }
                map[xx][yy][j] ^= (1 << id(str[i]));///a ^ pow(2,n)是将a的第n位取反
            }
        }
        if(!bfs(X1, Y1, W1))    cout << "  No Solution Possible" << endl;
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值