UVA 816 bfs

来源:互联网 发布:yum 安装vim 编辑:程序博客网 时间:2024/05/18 03:13

算法入门经典上面的题。题目链接 uva816

大致题意
有一个最多包含9*9个交叉点的迷宫。输入起点、离开起点时的朝向和终点,求一条最短路(多解时任意输出一个即可)。详细题意请看原题

思路
其实就是bfs,但是难点在于转向,将四个方向和3种转弯方式编号为0~3和0~2。
下面是转弯函数的实现

const char *dirs="NESW"; const char *turns="FLR";int dir_id(char c) {    return strchr(dirs,c)-dirs;}int turn_id(char c){    return strchr(turns,c)-turns;}const int dr[]={-1, 0, 1,  0};const int dc[]={ 0, 1, 0, -1};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);}

输入的时候读取交点的信息要注意处理。
利用has_edge[r][c][dir][turn]标记在坐标(r,c)处朝向dir转向turn能否成功。

AC代码

#include<iostream>//不需要判断边界、移动方向已经确定 #include<cstdio>#include<cstring>#include<queue>#include<vector>#include<sstream> using namespace std;int r0,c0,r1,c1,r2,c2;//r0、c0表示出发坐标 r2、c2是终点坐标char dir0;//出发方向 const int maxn=11;int has_edge[maxn][maxn][4][3],d[maxn][maxn][4];struct node{    int r,c,dir;//r行 c列 dir方向     node(int tr,int tc,int tdir)    {        r=tr;c=tc;dir=tdir;    }    node()    {    }};node p[maxn][maxn][4];const char *dirs="NESW"; const char *turns="FLR";int dir_id(char c) {    return strchr(dirs,c)-dirs;}int turn_id(char c){    return strchr(turns,c)-turns;}const int dr[]={-1, 0, 1,  0};const int dc[]={ 0, 1, 0, -1};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];    }    //打印解    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 bfs(){    int t=dir_id(dir0);    d[r0][c0][t]=0;    node temp(r0,c0,t);    d[r1][c1][t]=1;    node v(r1,c1,t);    p[r1][c1][t]= temp;    queue<node>q;    q.push(v);    while(!q.empty())    {    node u=q.front();    q.pop();    if(u.r==r2&&u.c==c2)     {        print_ans(u);        return;    }    for(int i=0;i<3;i++)    {        if(has_edge[u.r][u.c][u.dir][i])        {            v=walk(u,i);            if(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");}int main(void){    string name,pos;    int r,c;    string str;    stringstream ss;    while(cin>>name&&name!="END")    {        cin>>r0>>c0>>dir0>>r2>>c2;        //计算进入迷宫的坐标         if(dir0=='N')      {r1=r0-1;c1=c0;}        else if(dir0=='E') {r1=r0;c1=c0+1;}        else if(dir0=='W') {r1=r0;c1=c0-1;}        else               {r1=r0+1;c1=c0;}        memset(d,-1,sizeof(d));        memset(has_edge,0,sizeof(has_edge));        memset(p,0,sizeof(p));         getchar();        while(getline(cin,pos)&&pos!="0")        {            ss<<pos;            ss>>r>>c;            while(ss>>str)            {                if(str[0]!='*')                {                int dir=dir_id(str[0]);                for(int i=1;i<str.size();i++)                {                int turn=turn_id(str[i]);                has_edge[r][c][dir][turn]=1;                }                }            }            ss.clear();        }        cout<<name<<"\n";        bfs();    }    return 0;}

如有不当之处欢迎指出!

0 0
原创粉丝点击