zoukankan      html  css  js  c++  java
  • uva 10047 The Monocycle

    献上题意:个你一个转轮,有5种颜色,为了5中颜色的位置是确定的,为了方便处理我们用01234来表示绿,黑,红,蓝,白。轮子可以沿着它的方向滚动(只能是它当前的方向不能相反方向),每滚动一次会到达另一个格子,着地的颜色会改变,变了之前颜色的下一个,例如当前是绿色着地下一次就是黑色,依次是红蓝白。也可以原地转动(顺逆时针都可以),原地转动其实就是改变了轮子的滚动方向,原地转动每次能转90度。原地转动一次和滚动一次时间都是1秒。另外轮子有4个方向,上北下南左西又东。

    另外给你n*m个格子,有些格子不能到达,用#表示,给你起点S和终点T。在起点时轮子方向规定向北,绿色着地,然后滚动到终点,要求绿色着地,但是方向不做要求,问能不能做到,能的话输出最小时间

     

    用一个结构体表示状态,x,y,d,c,t,分别是坐标(即行列),当前方向(0123表示上右下左),当前颜色,时间

    然后用四维数组标记vis[x][y][d][c]来标记状态,这个很容易想到,仔细想想吧不说了

    因为求最短时间,显然应该用bfs,然后就开始bfs,bfs是以时间为标准的(第一次就是没搞清这个关系,过了几组数据交上次,WA,第二次改回来就通过了),把0秒的所有可能的状态都找出来入队(其实就是起始状态),然后把1秒所有可能的状态找出来入队,就这样bfs。然后注释写得比较详细,这里就不说了,看代码应该也能懂

    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    #define MAX 30
    #define D 4  //4个方向(北,东,南,西分别为0,1,2,3)
    #define C 5  //5中颜色(绿,黑,红,蓝,白分别为0,1,2,3,4)
    bool g[MAX][MAX];
    bool vis[MAX][MAX][D][C];  //分别表示横纵坐标,方向,颜色
    int sx,sy,ex,ey;     //起点和终点的坐标
    int n,m;
    struct node
    {
        int x,y;  //坐标
        int d;    //方向
        int c;    //颜色
        int t;    //时间
    };
    struct node ans;
    queue <struct node> q;
    int dd[D][2]={ {-1,0},{0,1},{1,0},{0,-1} }; //四个方向滚动之后的坐标变化
    void init()
    {
        memset(g,0,sizeof(g));
        memset(vis,0,sizeof(vis));
        for(int i=0; i<=m+1; i++)  //迷宫的外围上下两边沿不能访问
            g[0][i]=g[n+1][i]=1;
        for(int i=0; i<=n+1; i++)  //迷宫的外围左右两边沿不能访问
            g[i][0]=g[i][m+1]=1;
        return ;
    }
    void input()
    {
        for(int i=1; i<=n; i++)
        {
            char s[MAX];
            scanf("%s",s+1);
            for(int j=1; j<=m; j++)
                if(s[j]=='#')
                    g[i][j]=1;
                else if(s[j]=='S')
                { sx=i; sy=j;}
                else if(s[j]=='T')
                { ex=i; ey=j;}
        }
    /*
        for(int i=0; i<=n+1; i++)
        {
            for(int j=0; j<=m+1; j++)
                printf("%d ",g[i][j]);
            printf("\n");
        }
        printf("%d   %d\n%d  %d\n",sx,sy,ex,ey);
    */
        return ;
    }
    /*
    void print_node(struct node t) //仅供测试 { printf("坐标: %d %d",t.x,t.y); printf(" 方向: %d",t.d); printf(" 颜色: %d",t.c); printf(" 时间: %d",t.t); printf("\n"); return ; }
    */
    int BFS() { int FIND,x,y,d,c,t; struct node t1,t2; while(!q.empty()) q.pop(); //第一个节点的信息 t1.x=sx; //坐标就是起点坐标 t1.y=sy; //坐标就是起点坐标 t1.d=0; //起点方向规定向北 t1.c=0; //起点颜色规定绿色 t1.t=0; //地点时间为0 vis[sx][sy][0][0]=1; //这个状态已经用过 q.push(t1); //起点入队 FIND=0; //标记是否成功 while(!q.empty()) { t1=q.front(); //读取队头元素的信息 q.pop(); //队头元素出队 //print_node(t1); if(t1.x==ex && t1.y==ey && t1.c==0) //来到终点并且颜色为绿色 { ans=t1; FIND=1; break; } //原地顺时针旋转 x=t2.x=t1.x; y=t2.y=t1.y; d=t2.d=(t1.d+1)%4; c=t2.c=t1.c; t=t2.t=t1.t+1; if(!vis[x][y][d][c]) { vis[x][y][d][c]=1; q.push(t2); } //原地逆时针旋转 x=t2.x=t1.x; y=t2.y=t1.y; d=t2.d=(t1.d+3)%4; c=t2.c=t1.c; t=t2.t=t1.t+1; if(!vis[x][y][d][c]) { vis[x][y][d][c]=1; q.push(t2); } //第一次就是把原地的3种旋转都放进去(即转180也放进去),是错的 //因为转动180度用时是2秒,不是按照时间来bfs,要严格按照时间来bfs //向当前方向移动 x=t2.x=t1.x+dd[t1.d][0]; //计算新的坐标 y=t2.y=t1.y+dd[t1.d][1]; d=t2.d=t1.d; //方向不变 c=t2.c=(t1.c+1)%5; //新的颜色 t=t2.t=t1.t+1; //时间+1 if(g[x][y]) continue; //该点不能访问 if(!vis[x][y][d][c]) //该状态没有被用过 { vis[x][y][d][c]=1; q.push(t2); } } return FIND; } int main() { int T=0; while(scanf("%d%d",&n,&m)!=EOF && n && m) { T++; init(); input(); if(T>1) printf("\n"); printf("Case #%d\n",T); if(BFS()) printf("minimum time = %d sec\n",ans.t); else printf("destination not reachable\n"); } return 0; }
  • 相关阅读:
    异地主从双机热备份实战
    基于Crawler4j的WEB爬虫
    【转】TCP拥塞控制
    js定时器setTimeout和setInterval的使用
    制作 macOS Sierra U盘USB启动安装盘方法教程 (亲测)
    VMware 14 安装 macOS10.13 详细图文教程
    解决多线程下@Autowired无法注入
    MySQL 使用自增ID主键和UUID 作为主键的优劣比较详细过程(从百万到千万表记录测试)
    关于MYSQL
    关于Mybaits
  • 原文地址:https://www.cnblogs.com/scau20110726/p/2769970.html
Copyright © 2011-2022 走看看