UVa816

原创 2015年07月10日 00:02:20
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <stack>
#include <string>
#include <queue>
#include <iostream>
using namespace std;

struct Node{
    int x,y,dir;
    Node(int xx,int yy,int dd){
        x=xx;y=yy;dir=dd;
    }
    Node(){}
};
Node parents[10][10][4];//父亲结点,用于打出路径
bool has_edge[10][10][4][3];//保存是否有此行、列、面向、转向
int dist[10][10][4];//保存此结点的深度,可用于求最短路径的长度

int x0,y0,dir;//开始点
int x2,y2;//结束点
int x1,y1;//开始点的下一个点
int success;//是否有路标记

const char* directions = {"NESW"};//面向为北东南西
const char* turns = {"FLR"};//转向为直左右
int dir_id(char& c) { return strchr(directions,c)-directions; }
int turn_id(char& c) { return strchr(turns,c)-turns; }
int turnX[4]={-1,0,1,0};//根据面向的方向,计算下一步的坐标
int turnY[4]={0,1,0,-1};

bool inSide(int x,int y) { return x>0&&x<10&&y>0&&y<10; }
Node walk(Node& a,int t);
void bfs();
void print_path(Node top);
void printTest();
int main()
{
    char caseName[21];
    while(gets(caseName)&&strcmp(caseName,"END")!=0)
    {
        memset(has_edge,0,sizeof(has_edge));
        success=0;
        char tmpCh;
        cin>>x0>>y0>>tmpCh>>x2>>y2;
        dir=dir_id(tmpCh);
        x1=x0+turnX[dir];
        y1=y0+turnY[dir];
        int x,y;
        while(cin>>x && x!=0)
        {
            cin>>y;
            char tmpStr[5];
            while(cin>>tmpStr && tmpStr[0]!='*')
            {
                int dirID=dir_id(tmpStr[0]);
                int len=strlen(tmpStr);
                for(int i=1;i<len;i++)
                    has_edge[x][y][dirID][turn_id(tmpStr[i])] = 1;
            }
        }
        //printTest();
        getchar();//下一个循环有gets
        printf("%s\n",caseName);
        bfs();
        if(success==0)
            printf("  No Solution Possible\n");
    }
    return 0;
}

void print_path(Node top)
{
    stack<Node> sk;
    while(1)//遍历父亲,将结点逐个进栈,用dist判断退出循环条件,用parents判断难以处理出现相同结点问题
    {
        //printf("%d %d %c\n",top.x,top.y,directions[top.dir]);
        //getchar();
        sk.push(top);
        if(dist[top.x][top.y][top.dir]==0){
            sk.push(Node(x0,y0,dir));//开始点单独处理
            break;
        }
        top=parents[top.x][top.y][top.dir];
    }
    int len=sk.size();
    for(int sum=0;!sk.empty();)
    {
        if(sum%10==0)
            printf(" ");
        printf(" (%d,%d)",sk.top().x,sk.top().y);
        sk.pop();
        if(++sum%10==0)
            printf("\n");
    }
    if(len%10!=0)
        printf("\n");
}

void bfs()
{
    queue<Node> queues;
    memset(dist,-1,sizeof(dist));
    memset(parents,0,sizeof(parents));
    Node now(x1,y1,dir),top;

    dist[now.x][now.y][now.dir]=0;
    queues.push(now);
    while(!queues.empty())
    {
        now=queues.front();
        //printf("--%d %d %c\n",now.x,now.y,directions[now.dir]);
        queues.pop();
        if(now.x==x2&&now.y==y2){
            print_path(now);
            success=1;
            return;
        }
        for(int i=0;i<3;i++){
            top=walk(now,i);
            if(has_edge[now.x][now.y][now.dir][i] && inSide(top.x,top.y) && dist[top.x][top.y][top.dir]<0){//now有此转向,且top在范围内,且top没有被访问
                dist[top.x][top.y][top.dir]=dist[now.x][now.y][now.dir]+1;
                parents[top.x][top.y][top.dir]=now;
                queues.push(top);
            }
        }
    }
}

Node walk(Node& a,int t)
{
    Node tmp;
    if(t==0) tmp.dir=a.dir;//直走方向不变
    else if(t==1) tmp.dir=(a.dir+3)%4;//左转为逆时针
    else if(t==2) tmp.dir=(a.dir+1)%4;//右转为顺时针
    else printf("walk error\n");
    tmp.x=a.x+turnX[tmp.dir];
    tmp.y=a.y+turnY[tmp.dir];
    return tmp;
}

void printTest()
{
    for(int i=0;i<10;i++)
        for(int j=0;j<10;j++)
            for(int k=0;k<4;k++)
                for(int l=0;l<3;l++)
                    if(has_edge[i][j][k][l])
                        printf("%d %d %c%c\n",i,j,directions[k],turns[l]);
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

UVa816 Abbott's Revenge

题意:走迷宫,在某个点,对于mou'g

uva816 Abbott's Revenge (BFS+回溯)

题目大意 给你个迷宫,求最短路,不过在每个点转弯的方向受进入方向的限制 思路 确定好每个点的状态,再用bfd求出最短路,注意记得用个数组保存节点,以方便输出 事实上很多细节都是参考刘汝...

uva 816 Abbott's Revenge (走迷宫BFS)

原题链接: https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&probl...

Uva oj 816 Abbott Revenge(BFS最短路)

原题链接:Here! 闲话:看到题目的时候还是很懵的,这个迷宫很特殊,特殊的地方在对于每一个点都多出来一些要求,比如进入一个交叉点的"朝向"( NESW,北东南西 )是不同的,对应不同的"朝向",出...

uva 816 - Abbott's Revenge(有一点难度的bfs迷宫题目)

就是典型的bfs,但这道题目的难点在于其条件的读取和判断并不简单,需要想办法来读取条件,也需要想办法来判断在每个点处能不能满足向下继续走的条件。 #include #include #include...

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

Problem Description 给你起点,给你起点的方向,给你终点,让你求起点到终点的最短路径。它会给出很多个点,告诉你在这个点你只能怎么走,”NEWS”分别对应北东南西,也就是上右下左,...

UVA 816 bfs

uva bfs

uva 816 有点复杂的BFS和宽度优先搜索模板 Abbott's Revenge

The 1999 World Finals Contest included a problem based on a dice maze. At the time the problem was ...

UVA - 816 Abbott's Revenge

原题链接 分析:本题和普通的迷宫在本质上是一样的,但是由于“朝向”也起到了关键作用,所以需要用一个三元组(r,c,dir)表示“位于(r,c),面朝dir”这个状态。假设入口的位置为(r0,...

UVA816(用BFS求最短路)(wf)

UVA816(用BFS求最短路)(wf)
  • Ema1997
  • Ema1997
  • 2016年06月10日 13:55
  • 341
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:UVa816
举报原因:
原因补充:

(最多只允许输入30个字)