• UVA 10047 The Monocycle


    白书上图论例题2

    题目大意是 M*N个格子 #不能走

    S是起点 T是终点

    上北下南左西右东

    一开始在S,朝向北,

    在每一个格子 可以左转90度 或者右转90度 或者朝向走1格

    问从起点到终点 计算重复格子 走5的整数倍个格子到终点 不限制最后朝向 最短时间是多少


    就像书上讲的那样

    每个点 拆成20个点

    (x,y,color,head)

    分别表示该点的坐标,走到该点 走过的格子%5,现在的朝向

    每次可以向(x,y,color,head-1) (x,y,color,head+1) (x+mx[head],y+my[head],(color+1)%5,head)走

    分别对应左转、右转和前进


    因为每次操作都是花费1

    所以直接bfs也可以 先搜到的终点一定是时间最少的

    这样还有一个好处就是不用扔set了 判重也方便

    其实这个不用set也可以。。。

    发现现在有点依赖stl了。。。


    这个题还有一个坑点 就是 每两组数据间输出一个空行

    但是最后一组只能有1个空行!


    我用spfa写的

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<map>
    #include<queue>
    using namespace std;
    const int lim = 26;
    const int lin = lim*lim*lim*lim*lim;
    const int inf = 0x3f3f3f3f;
    const int mx[4]={-1,0,1,0};
    const int my[4]={0,1,0,-1};
    
    int g[lim][lim];
    
    struct node
    {
        int x,y,color,head;
        node()
        {
            x=y=color=head=0;
        }
        node(int xx,int yy,int col,int hea)
        {
            x=xx;
            y=yy;
            color=col;
            head=hea;
        }
        bool operator<(const node h) const
        {
            if(h.x==x)
                if(h.y==y)
                    if(h.color==color)
                        return h.head<head;
                    else
                        return h.color<color;
                else
                    return h.y<y;
            else
                return h.x<x;
        }
    };
    
    node S,T;
    
    map<node,int>mp;
    
    queue<node>q;
    int d[lim*lim*20];
    int vis[lim*lim*20];
    int fst[lim*lim*20];
    int m,n;
    int r,c;
    char chin;
    int _case;
    
    void spfa()
    {
        while(!q.empty())
            q.pop();
        memset(d,0x3f,sizeof(d));
        memset(vis,0,sizeof(vis));
        q.push(S);
        mp[S]=++m;
        vis[m]=1;
        d[m]=0;
        while(!q.empty())
        {
            node u=q.front();
            q.pop();
            int uid=mp[u];
            vis[uid]=0;
            
            int x=u.x;
            int y=u.y;
            int color=u.color;
            int head=u.head;
            for(int i=-1;i<=1;i+=2)
            {
                int hhead=(head+i+4)%4;
                node v = node(x,y,color,hhead);
                if(mp[v]==0)
                {
                    mp[v]=++m;
                }
                int vid=mp[v];
                if(d[vid]>d[uid]+1)
                {
                    d[vid]=d[uid]+1;
                    if(!vis[vid])
                    {
                        vis[vid]=1;
                        q.push(v);
                    }
                }
            }
            
            int xx=x+mx[head],yy=y+my[head];
            int ccolor=(color+1)%5;
            if(xx>=1 && xx<=r && yy>=1 && yy<=c && g[xx][yy]==1)
            {
                node v = node(xx,yy,ccolor,head);
                if(mp[v]==0)
                {
                    mp[v]=++m;
                }
                int vid=mp[v];
                if(d[vid]>d[uid]+1)
                {
                    d[vid]=d[uid]+1;
                    if(!vis[vid])
                    {
                        vis[vid]=1;
                        q.push(v);
                    }
                }
            }
        }
        int ans = inf;
        for(int k=0;k<=3;k++)
        {
            node tt = node(T.x,T.y,0,k);
            ans=min(ans,d[mp[tt]]);
        }
        if(ans==inf)
        {
            printf("Case #%d
    destination not reachable
    ",_case);
        }
        else
        {
            printf("Case #%d
    minimum time = %d sec
    ",_case,ans);
        }
    }
    int main()
    {
        while(scanf("%d%d",&r,&c)==2)
        {
            if(r==0 && c==0)
                return 0;
            if(_case>=1)
                printf("
    ");
            m=0;
            mp.clear();
            _case++;
            memset(fst,-1,sizeof(fst));
            for(int i=1;i<=r;i++)
            {
                for(int j=1;j<=c;j++)
                {
                    scanf(" %c",&chin);
                    if(chin=='#')
                        g[i][j]=0;
                    else
                    {
                        g[i][j]=1;
                        if(chin=='S')
                        {
                            S.x=i;
                            S.y=j;
                            S.color=0;
                            S.head=0;
                        }
                        if(chin=='T')
                        {
                            T.x=i;
                            T.y=j;
                            T.color=0;
                        }
                    }
                }
            }
            spfa();
        }
        return 0;
    }
  • 相关阅读:
    总结@ 在C# 中的用法
    如何在多线程中调用winform窗体控件
    jQuery对象和DOM对象原来不一样啊
    以编程方式使用 Word 中的内置对话框
    C#中Application.DoEvents()的作用
    本地设置正常,放服务器上就报 System.Security系统找不到指定的文件解决方法
    复制选中的listbox内容
    将一列数据拼接成一个字符串
    服务器不能复制粘贴问题处理
    获取Token不完整问题
  • 原文地址:https://www.cnblogs.com/abgnwl/p/6550332.html
Copyright © 2020-2023  润新知