【BFS + 保存路径】UVA - 816 Abbott's Revenge

21 篇文章 0 订阅
15 篇文章 0 订阅

Problem Description

给你起点,给你起点的方向,给你终点,让你求起点到终点的最短路径。它会给出很多个点,告诉你在这个点你只能怎么走,”NEWS”分别对应北东南西,也就是上右下左,”FLR”分别代表直走 左转 右转。所以假如一个路口给你 “WLF”就代表如果你进来的时候朝下,你就只能左转或者直走。

代码:复杂点就多了 转弯方向的问题而已,理解了也不难。当前的方向,怎么转朝哪,都转换成整数存起来。这样好判断

#include<bits/stdc++.h>
using namespace std;
struct node
{
    int r, c, dir;
};
int vis[15][15][4];//标记是否走过
node Pre[15][15][4];//记录路径
int has_edge[15][15][4][3];//判断能否走
int dr[5] = {-1, 0, 1, 0}; //上右下左
int dc[5] = {0, 1, 0, -1};
char dirs[5] = {"NESW"};//上右下左 0123
char turns[4] = {"FLR"};//直走,左转,右转 0,1,2
char s[30], s1[30];//最开始输入的字符串,中间过程输入的字符串
int r0, c0, rr, cc, r1, c1, dir1, rx, cx;//起始点,终点,起始点的下一步的点,其他点,
int dir_id(char c) {return strchr(dirs, c) - dirs;}//求当前方向对应的下标
int turn_id(char c) {return strchr(turns, c) - turns;}//求怎么转的下标
node walk(node u, int i)
{
    int dir = u.dir;
    if(i == 1) dir = (dir + 3) % 4;//左转
    if(i == 2) dir = (dir + 1) % 4;//右转
    return (node){u.r + dr[dir], u.c + dc[dir], dir};
}
void print_ans(node u)
{
    vector<node> a;
    for(;;)
    {
        a.push_back(u);//存入数组
        if(vis[u.r][u.c][u.dir] == 0) break;
        u = Pre[u.r][u.c][u.dir];
    }
    printf("%s\n", s);//输出
    printf("  (%d,%d)", r0, c0);
    int cnt = 1;
    for(int i = a.size() - 1; i >= 0; i--)
    {
        if(cnt % 10 == 0) printf("\n  ");
        else printf(" ");
        printf("(%d,%d)", a[i].r, a[i].c);
        cnt++;
    }
    printf("\n");
}
void bfs()
{
    queue<node> q;
    memset(vis, 0, sizeof(vis));//初始化
    q.push((node){r1, c1, dir1});//存入起始点的下一个点
    while(!q.empty())
    {
        node u = q.front();
        q.pop();
        if(u.r == rr && u.c == cc) {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] && !vis[v.r][v.c][v.dir])//判断能否走
            {
                vis[v.r][v.c][v.dir] = vis[u.r][u.c][u.dir] + 1;//标记走过的点
                Pre[v.r][v.c][v.dir] = u;//记录路径保存上一个点
                q.push((node){v.r, v.c, v.dir});//存入
            }
        }
    }
    printf("%s\n", s);//找不到终点
    printf("  No Solution Possible\n");
}
int main()
{
    while(~scanf("%s", s))
    {
        if(strcmp(s, "END") == 0) break;//结束退出循环
        scanf("%d %d %s %d %d", &r0, &c0, s1, &rr, &cc);
        memset(has_edge, 0, sizeof(has_edge));
        dir1 = dir_id(s1[0]);//求起始点的下一个点
        r1 = r0 + dr[dir1];
        c1 = c0 + dc[dir1];
        for(;;)
        {
            scanf("%d", &rx);
            if(!rx) break;//如果是0退出循环
            scanf("%d", &cx);
            while(~scanf("%s", s1))
            {
                if(s1[0] == '*') break;//退出循环
                for(int i = 1; i < strlen(s1); i++)//存入,后面判断能否走
                {
                    has_edge[rx][cx][dir_id(s1[0])][turn_id(s1[i])] = 1;//分别对应行,列下标,方向,如何转,能走标记1
                }
            }
        }
        bfs();
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值