HDU-3713:Double Maze(双重BFS)


题目链接:点击打开链接


题目大意:

有两个迷宫,每个迷宫有自己的起点终点,两个迷宫分别有一个球在起点,你的命令同时对两个球都生效,若其中一个碰到障碍无法移动。若其中一个球掉到洞中或者出边界即为失败。


解题思路:

本质上就是个简单的BFS,状态搞个四维数组存一下,每次依次判断清楚哪个方向有障碍就好,路径用 string储存,因为要最小字典序,所以方向要注意一下。比赛的时候因为读错题,以为其中一个到终点就可以不用管了,导致最终代码异常复杂。本着赛后AC原则,赛后将代码删了些东西就tm过了。唉,以后一定看清楚题目再写题,这次连样例都没看,确实是对自己的蜜汁自信,也毁了自己。

本题唯一复杂的地方就是每个点的性质是用二进制表示的,所以熟悉位运算之后就很容易搞了。细节部分看代码吧,自己代码比较繁琐,毕竟比赛时候写的,Orz,


#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <algorithm>
#include <set>
#include <functional>
#define rank ra
#define lson rt<<1
#define rson rt<<1|1
#define pb push_back
using namespace std;
typedef long long ll;
int n;
int dx[4]={1,0,0,-1};   //按一定顺序的方向数组
int dy[4]={0,-1,1,0};
int sx1,sy1,sx2,sy2;    //分别记录两个图的起点终点
int ex1,ey1,ex2,ey2;
int ma1[7][7];      //用于bfs的两个图
int ma2[7][7];      
int ma[22][7][7];  
bool vis[7][7][7][7];       //记录是否到达过当前状态
int di[5]={1,0,2,3};        //记录每种方向判断是否有障碍需要向右移几位
struct node
{
    int x1,y1,x2,y2;        //记录当前状态
    string dir;
};
queue<node> que;
string ans;
bool check1(int xx1,int yy1,int xx2,int yy2)    //其中任意一个点为洞即不可走
{
    int kk1=ma1[xx1][yy1];
    int kk2=ma2[xx2][yy2];
    if(((kk1>>4)&1)==0||((kk2>>4)&1)==0)
        return 1;
    return 0;
}
bool vs(int xx1,int yy1,int xx2,int yy2)    //不符合情况的情况
{
    if(xx1<1||xx1>6||yy1<1||yy1>6||xx2<1||xx2>6||yy2<1||yy2>6||vis[xx1][yy1][xx2][yy2])
        return 1;
    return 0;
}
char vc(int i)
{
    if(i==0) return 'D';
    if(i==1) return 'L';
    if(i==2) return 'R';
    return 'U';
}
void bfs()
{
    node st;
    memset(vis,0,sizeof(vis));
    while(!que.empty())
        que.pop();
    st.x1=sx1;st.y1=sy1;
    st.x2=sx2;st.y2=sy2;
    vis[st.x1][st.y1][st.x2][st.y2]=1;
    que.push(st);
    int flag=0;
    while(!que.empty())
    {
        node k=que.front();
        que.pop();
        if(k.x1==ex1&&k.x2==ex2&&k.y1==ey1&&k.y2==ey2)  //都到达终点就结束
        {
            flag=1;
            ans=k.dir;
            break;
        }
        int kk1=ma1[k.x1][k.y1];
        int kk2=ma2[k.x2][k.y2];
        for(int i=0;i<4;i++)
        {
            int xx1=k.x1;
            int yy1=k.y1;
            int xx2=k.x2;
            int yy2=k.y2;
            if(((kk1>>di[i])&1)==0)     //判断当前方向是否有障碍
            {
                xx1=k.x1+dx[i];
                yy1=k.y1+dy[i];
            }
            if(((kk2>>di[i])&1)==0)     //同上
            {
                xx2=k.x2+dx[i];
                yy2=k.y2+dy[i];
            }
            if(check1(xx1,yy1,xx2,yy2)||vs(xx1,yy1,xx2,yy2))    //不符合情况跳过
                continue ;
            node sk;
            sk.x1=xx1;sk.y1=yy1;
            sk.x2=xx2;sk.y2=yy2;
            sk.dir=k.dir+vc(i);
            vis[xx1][yy1][xx2][yy2]=1;
            que.push(sk);
        }
    }
    if(flag==0)
        ans="-1";
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        for(int k=1;k<=n;k++)
            for(int i=1;i<=6;i++)
                for(int j=1;j<=6;j++)
                scanf("%d",&ma[k][i][j]);       //记录所有地图
        for(int k=1;k<n;k++)            //依次赋给两个地图
        {
            for(int i=1;i<=6;i++)
            {
                for(int j=1;j<=6;j++)
                {
                    ma1[i][j]=ma[k][i][j];
                    int k=ma1[i][j];
                    if((k>>5)&1)    //找起点
                    {
                        sx1=i;
                        sy1=j;
                    }
                    if((k>>6)&1)    //找终点
                    {
                        ex1=i;
                        ey1=j;
                    }
                }
            }
            for(int i=1;i<=6;i++)
            {
                for(int j=1;j<=6;j++)
                {
                    ma2[i][j]=ma[k+1][i][j];
                    int k=ma2[i][j];
                    if((k>>5)&1)
                    {
                        sx2=i;
                        sy2=j;
                    }
                    if((k>>6)&1)
                    {
                        ex2=i;
                        ey2=j;
                    }
                }
            }
            bfs();          //进行bfs过程
            cout<<ans<<endl;
        }
    }
    return 0;
}








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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值