Uva816 Abbott's Revenge【bfs】【例题6-14】

题目:Abbott's Revenge

题意:一个9*9的迷宫,迷宫上的每个位置有不同的转弯方式,当你从不同的方向走到每个位置时有不同的转弯方式,最后求到目的地的最短路径的过程!

思路:

输入需要处理:按题意输入,但是将坐标,方向和转弯方式要存放has_edge[x][y][dir][turn]的下表,将此位置置为1说明此位置有路!

进行dfs计算最短路:每出队一个点,将它的3个转弯方式计算下下个状态,看看有没有,计算下一个状态时:要考虑转弯不同方向会变:F正常,L逆时针,R顺时针!

输出处理:将最后一个状态开始,倒着存入vector中,每次利用p[r][c][dir](bfs时存放每次的根节点)获取上一次的根节点!最后倒的输出即可!

参考:入门经典-例题6-14-P166 + 点击打开链接

代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <queue>
#include <vector>
using namespace std;
const int maxn = 10;
const char* dirs = "NESW";//方向
const char* turns = "FLR";//转弯方式
const int dr[] = {-1,0,1,0};
const int dc[] = {0,1,0,-1};
struct Node{//状态
    int r,c,dir;
    Node(){};
    Node(int rr,int cc,int ddir){
        r = rr;c = cc;dir = ddir;
    }
} ;
int dir_id(char c){return strchr(dirs,c) - dirs;}//计算方向,因为strchr返回指针位置,而dirs也定义的指针,所以相减可得方向位置
int turn_id(char c){return strchr(turns,c) - turns;}//同上
int sr,sc,er,ec,dir,r0,c0;
int has_edge[maxn][maxn][maxn][maxn];//存放输入的位置
int d[maxn][maxn][maxn];//表示初始状态到(r,c,dir)的最短路长度
Node p[maxn][maxn][maxn];//保存状态(r,c,dir)在BFS树的父节点
bool inside(int x,int y){
    if(x > 0 && x < 10 && y > 0 && y < 10) return true;
return false;}
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);}//返回后续状态
void print_ans(Node u){//打印函数
    vector<Node>nodes;//存入集合
    for(;;){//倒的存入
        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));

    int cnt = 0;
    for(int i=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");
}

void solve_bfs(){//bfs寻找最短路
    queue<Node>q;
    memset(d,-1,sizeof(d));
    Node u(sr,sc,dir);
    d[u.r][u.c][u.dir] = 0;
    q.push(u);
    while(!q.empty()){
        Node u = q.front();q.pop();
        if(u.r == er && u.c == ec){ 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");//无解
return;}
int main(){
    string name;
    char dir_str[20];
    int x,y;
    while(cin >> name && name != "END"){
        memset(has_edge,0,sizeof(has_edge));
        cout << name<< endl;
        scanf("%d%d%s%d%d",&r0,&c0,dir_str,&er,&ec);
        dir = dir_id(dir_str[0]);
        sr = r0 + dr[dir];sc = c0 + dc[dir];
        while(scanf("%d",&x) && x){
            scanf("%d",&y);
            while(scanf("%s",dir_str) && dir_str[0] != '*'){
                int sdir = dir_id(dir_str[0]);//计算当前方向
                for(int i=1;dir_str[i] != '\0';i++){
                        int turn = turn_id(dir_str[i]);//计算当前转弯方式
                        has_edge[x][y][sdir][turn] = 1;//此位置存在点的方向和转弯,标记为1
                }
            }
        }
        solve_bfs();//bfs求解
    }
return 0;}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值