UVa816

#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]);
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值