HDU-3713---Double Maze (bfs) 详细解释

Double Maze

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1353    Accepted Submission(s): 516



Problem Description
Unlike single maze, double maze requires a common sequence of commands to solve both mazes. See the figure below for a quick understanding.



A maze is made up of 6*6 cells. A cell can be either a hole or a square. Moreover, a cell may be surrounded by barriers. There is ONLY one start cell (with a ball) and ONLY one end cell (with a star) in a single maze.These two cells are both squares. It is possible that the start cell and the end cell are the same one. The goal of a single maze is to move the ball from the start cell to the end cell. There are four commands in total,'L', 'D', 'R' and 'U' corresponding to moving the ball left, down, right and up one cell, respectively. The barriers may make the commands take no effect, i.e., the ball does NOT move if there is a barrier on the way.
When the ball gets to a hole or outside of the maze, it fails. A double maze is made up of two single mazes. The commands control two balls simultaneously, and the movements of two balls are according to the rules described above independently. Both balls will continue to move simultaneously if at least one of the balls has not got to the end cell.
So, a ball may move out of the end cell since the other ball has not been to the target. A double maze passes when both balls get to their end cells, or fails if either of the two mazes fails. The goal of double maze is to get the shortest sequence of commands to pass. If there are multiple solutions, get the lexical minimum one.
To simplify the input, a cell is encoded to an integer as follows. The lowest 4 bits signal the existence of the barriers around a cell. The fifth bit indicates whether a cell is a hole or not. The sixth and seventh bits are set for the start cell and end cell. Details are listed in the following table with bits counted from lowest bit. For a barrier, both of the two adjacent cells will have the corresponding barrier bit set. Note that the first two mazes in the sample input is the encoding of two mazes in the figure above, make sure you understand the encoding right.
 

Input
The first line of input gives the total number of mazes, T (1 < T ≤ 20). Then follow T mazes. Each maze is a 6*6 matrix, representing the encoding of the original maze. There is a blank line between mazes.
 

Output
For every two consecutive mazes, you should treat them as a double maze and output the answer. So there are actually T - 1 answers. For each double maze, output the shortest sequence of commands to pass. If there are multiple solutions, output the lexicographically minimum one. If there is no way to pass, output -1 instead.
 

Sample Input
  
  
3 16 0 18 16 18 24 20 19 24 16 28 1 18 28 17 0 22 17 25 20 17 18 88 20 2 16 48 28 17 16 24 16 16 20 23 1 16 0 18 16 18 24 20 19 24 20 29 1 18 28 17 16 22 17 8 20 1 18 24 20 19 80 48 24 16 0 24 16 16 16 22 19 18 16 18 16 18 80 24 18 24 16 24 18 18 24 0 0 18 24 24 18 0 0 24 18 18 24 18 16 18 24 56 18 24 18 24 18
 

Sample Output
  
  
RRLULLLRRDLU RURDRLLLURDULURRRRRDDU
 

Author
GAO, Yuan
 

Source
2010 Asia Chengdu Regional Contest

题意:给你两个迷宫,每个迷宫里面有起点和终点,球为起点,星为终点,每次两个迷宫里面的球做相同的移动,直到两个求同时到达终点,否则一直移动,若不能同时到达终点输出-1,能的话就输出字典序最小的最短路径,每两个图一组;

思路:这题求最短路很容易想到bfs,然后按字典序最小的输出,只需要bfs的时候按D,L,R,U这个顺序去搜就行,这题有两个图,我们用一个四维的数组来标记;

解释一下样例输入:输入是输的整数,我们要把它转化成二进制来看,看第一个迷宫的(1,1)这个点为16,二进制为10000,后四位对应表中的前四个,都为0表示该点上下左右都没有障碍,第五位为1,表示该点是一个方块,再看(4,5)这个点为88,二进制为1011000,第4位为1,表示上面有障碍,第5位为1,表示该点是方块,第七位为1,表示该点是终点,正好和第一个图对应,其他点一样;

AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#define N 10
using namespace std;
int t,a[N][N],b[N][N];
int vis[N][N][N][N];
struct node
{
    int x,y;
    int xx,yy;
    int x1,y1,x2,y2;
}start,over,pre[N][N][N][N];//起始点,终止点,记录路劲的数组
int next[4][2]={1,0,0,-1,0,1,-1,0};//按下,左,右,上定义的方向数组
char s[4]={'D','L','R','U'};
int barrier[4]={2,1,4,8};//障碍物
queue<node> que;
void print(int x1,int y1,int x2,int y2)//递归打印路径
{
    int tx1=x1,ty1=y1,tx2=x2,ty2=y2;
    if(tx1==start.x&&ty1==start.y&&tx2==start.xx&&ty2==start.yy)return;
    int _x=pre[tx1][ty1][tx2][ty2].x;
    int _y=pre[tx1][ty1][tx2][ty2].y;
    int _xx=pre[tx1][ty1][tx2][ty2].xx;
    int _yy=pre[tx1][ty1][tx2][ty2].yy;
    print(_x,_y,_xx,_yy);
    for(int i=0;i<4;i++)
    {
        if(_x+next[i][0]==tx1&&_y+next[i][1]==ty1||_xx+next[i][0]==tx2&&_yy+next[i][1]==ty2)
            printf("%c",s[i]);
    }
    return;
}
void bfs()
{
    node q,tmp;
    que.push(start);//将起点入队
    vis[start.x][start.y][start.xx][start.yy]=1;//标记起点
    while(que.size())
    {
        q=que.front();
        que.pop();
        if(q.x==over.x&&q.y==over.y&&q.xx==over.xx&&q.yy==over.yy)//两个同时到达终点
        {
             print(q.x,q.y,q.xx,q.yy);
             printf("\n");
             return;
        }
        for(int i=0;i<4;i++)//遍历四个方向,如果下一个方向右障碍,则呆在原地,否者走向下一点
        {
            if((a[q.x][q.y]&barrier[i]))//第一个图的点
            {
                tmp.x=q.x;
                tmp.y=q.y;
            }
            else
            {
                 tmp.x=q.x+next[i][0];
                 tmp.y=q.y+next[i][1];
            }
            if((b[q.xx][q.yy]&barrier[i]))//第二个图
            {
                tmp.xx=q.xx;
                tmp.yy=q.yy;

            }
            else
            {
                tmp.xx=q.xx+next[i][0];
                tmp.yy=q.yy+next[i][1];
            }
            if((a[tmp.x][tmp.y]&16)&&(b[tmp.xx][tmp.yy]&16)&&vis[tmp.x][tmp.y][tmp.xx][tmp.yy]==0)//如果下一个点不是洞并且没被标记过则入队
            {
                vis[tmp.x][tmp.y][tmp.xx][tmp.yy]=1;
                pre[tmp.x][tmp.y][tmp.xx][tmp.yy].x=q.x;
                pre[tmp.x][tmp.y][tmp.xx][tmp.yy].y=q.y;
                pre[tmp.x][tmp.y][tmp.xx][tmp.yy].xx=q.xx;
                pre[tmp.x][tmp.y][tmp.xx][tmp.yy].yy=q.yy;
                que.push(tmp);
            }
        }
    }
    printf("-1\n");
    return;
}
int main()
{
    scanf("%d",&t);
    for(int v=0;v<t;v++)
    {
        if(v&1){
            for(int i=1;i<=6;i++){
                for(int j=1;j<=6;j++){
                    scanf("%d",&a[i][j]);
                    if(a[i][j]&32){//该点为起点,&运算如果两个数的同一二进制位都为1则为1
                        start.x=i;
                        start.y=j;
                    }
                    if(a[i][j]&64){//该店为终点
                        over.x=i;
                        over.y=j;
                    }
                }
            }
        }
        else{
            for(int i=1;i<=6;i++){
                for(int j=1;j<=6;j++){
                    scanf("%d",&b[i][j]);
                    if(b[i][j]&32){
                        start.xx=i;
                        start.yy=j;
                    }
                    if(b[i][j]&64){
                        over.xx=i;
                        over.yy=j;
                    }
                }
            }
        }
        if(v==0)continue;
        memset(vis,0,sizeof(vis));
        bfs();
        while(que.size())que.pop();//清空队列
    }
    return 0;
}


 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值