UVA816简单最短路径

这道题目很麻烦,题意需要好好理解;

说一下我从这道题中学到的东西:

1》求最短路径时,一定要注意起点是哪一个,然后将起点入队,去走这个起点能够到达的下一个点,并入队。注意vis的使用

2》打印最短路径的时候,先用指针指向last,然后将这个点并入vector,而后将指针指向parent,继续vector,直到刚进去的那个节点是起点为止。

3》对于东西南北方向的计算,即:向左转向右转与方向的关系

4》如果输入的时候循环比较多的话,直接写到分开写到各个函数中,因为循环的break只能跳出一层循环,而函数的return可以跳出整个循环。

下面贴出代码:

//最短路径的关键在于为每一个位置(状态)找到它对应的父节点,从父节点可以找到它的上一个节点的位置信息
//如果是使用二维数组表示的u/v的这种类型的图,那非常的简单,就是在G[v]中找到v的上一个节点u,然后P[u]=v
//但此题比较的复杂
//向左转就减一下,向右转就加一下。
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
using namespace std;

const int maxn = 10;

//前两个是横纵坐标,第三个是进入这个点时的状态,第四个是转动的方向0直走,1右转,2左转
char G[maxn][maxn][4][3];
char vis[maxn][maxn][4];
int r_start,c_start,r_last,c_last;
struct node
{
    int row;
    int col;
    int dir;
    node(int a = 0,int b = 0,int dir = 0):row(a),col(b),dir(dir){}
};

node parent[maxn][maxn][4];
node fir;
node last;
node start;

string name;
int dir_id(char dir)
{
    if(dir == 'N')
        return 0;
    if(dir == 'E')
        return 1;
    if(dir == 'S')
        return 2;
    if(dir == 'W')
        return 3;
}
bool read_in()
{
    memset(G,0,sizeof(G));
    memset(vis,0,sizeof(vis));
    cin>>name;
    if(name == "END")
    {
        return false;
    }
    char dir[5];
    scanf("%d%d%s%d%d",&r_start,&c_start,dir,&r_last,&c_last);
    fir.col = c_start;
    fir.row = r_start;
    fir.dir = dir_id(dir[0]);
    //G[fir.row][fir.col][fir.dir][0] = 1;//直走是可以的
    last.row = r_last;
    last.col = c_last;
    for(;;)
    {
        int r,c;
        scanf("%d",&r);
        if(r == 0)
            return true;
        scanf("%d",&c);
        for(;;)
        {
            scanf("%s",dir);
//printf("%s\n",dir);
            if(dir[0] == '*')
                break;
            int len = strlen(dir);
            for(int i = 1;i < len;i++)
            {
                if(dir[i] == 'L')
                    G[r][c][dir_id(dir[0])][2] = 1;
                else  if(dir[i] == 'R')
                    G[r][c][dir_id(dir[0])][1] = 1;
                else  if(dir[i] == 'F')
                    G[r][c][dir_id(dir[0])][0] = 1;
            }
        }
    }
}

node walk(node u,int turn)
{//先转向,再走
    int dir = u.dir;
    if(turn == 1)
        dir = (dir+1)%4;
    else if(turn == 2)
        dir = (dir+3)%4;
    if(dir==0)//面向北方
    {
        node v(u.row-1,u.col,dir);
        return v;
    }
    if(dir==1)//面向东
    {
        node v(u.row,u.col+1,dir);
        return v;
    }
    if(dir==2)//面向南
    {
        node v(u.row+1,u.col,dir);
        return v;
    }
    if(dir==3)//面向西方
    {
        node v(u.row,u.col-1,dir);
        return v;
    }
}
bool min_road()
{
    queue<node>Q;
    start=walk(fir,0);
    parent[start.row][start.col][start.dir] = fir;
    vis[start.row][start.col][start.dir] = 1;
    Q.push(start);
    while(!Q.empty())
    {
        node u = Q.front();
        if(u.row == r_last && u.col == c_last)
        {
            last = u;
             return true;
        }
        Q.pop();
        for(int i = 0;i<3;i++)
        {
            if(G[u.row][u.col][u.dir][i] == 1)
            {
                node v(walk(u,i));

              if(!vis[v.row][v.col][v.dir])
              {
//printf("%d  %d  %d  \n",v.row,v.col,v.dir);
                  vis[v.row][v.col][v.dir] = 1;
                  Q.push(v);
                  parent[v.row][v.col][v.dir] = u;
              }
            }
        }
    }
    return false;
}
int main()
{
#ifdef local
    freopen("input.txt","r",stdin);
    freopen("out.txt","w",stdout);
#endif
    while(read_in())
    {
        cout<<name<<endl;
        if(min_road())
        {
            vector<node>V;
            node u = last;
            for(;;)//将指针u进vector,判断u是不是起点,如果是,结束,如果不是将指针指向u的parent
            {
                V.push_back(u);//从最后开始
//printf("(%d %d)\n",u.row,u.col);
                if(u.row == start.row&&u.col == start.col&&u.dir==start.dir)
                    break;
                u = parent[u.row][u.col][u.dir];
            }
            V.push_back(fir);
            for(int i = V.size() - 1,j = 0;i >= 0;i--,j++)
            {
                if(j % 10 == 0)
                    printf(" ");
                printf(" (%d,%d)",V[i].row,V[i].col);
                if(j % 10 == 9||!i)
                    printf("\n");
            }
        }
        else
        {
            printf("  No Solution Possible\n");
        }

    }
    return 0;


    
}

猜你喜欢

转载自www.cnblogs.com/TorettoRui/p/10449935.html
今日推荐