hdu 1254 推箱子

/*
bfs+bfs,首先是上一步的人位置能否在某个方向推动箱子,然后就是箱子移动后的标记,开一个三维数组进行标记
前两维标记坐标,第三维标记箱子从什么方向推到该位置
*/
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;
int Map[10][10][2],n,m,Map1[10][10][4],bu[4][2]={0,1,0,-1,1,0,-1,0},bu1[4][2]= {0,-1,0,1,-1,0,1,0},Map2[10][10];
struct node
{
    int x1,y1,z;//点的横纵坐标和步数
    int x2,y2;//人的推箱子后的坐标表
} S,D;
int bfs1(int a,int b,int c,int d)//是否能达到箱子的四周(a,b是人的位置,c,d是箱子四周的某一个位置)
{
    int i;
    queue<node> v;
    while(!v.empty())
        v.pop();
    node l,r,t;
    t.x1=a;
    t.y1=b;
    t.z=0;
    memset(Map2,0,sizeof(Map2));
    Map2[t.x1][t.y1]=1;
    v.push(t);
    while(!v.empty())
    {


        l=v.front();
        v.pop();
        if(l.x1==c&&l.y1==d)
            return l.z;
        for(i=0; i<4; i++)
        {
            int aa=l.x1+bu[i][0];
            int bb=l.y1+bu[i][1];
            if(aa>=0&&aa<n&&bb>=0&&bb<m&&Map[aa][bb][1]!=1&&Map2[aa][bb]==0)
            {
                Map2[aa][bb]=1;
                r.x1=aa;
                r.y1=bb;
                r.z=l.z+1;
                v.push(r);
                if(r.x1==c&&r.y1==d)
                    return r.z;
            }
        }
    }
    return -1;
}
int bfs()
{
    memset(Map1,0,sizeof(Map1));
    queue<node> v;
    int i;
    node l,r;
    while(!v.empty())
        v.empty();
    v.push(S);
    while(!v.empty())
    {


        l=v.front();
        v.pop();
        if(l.x1==D.x1&&l.y1==D.y1)
            return l.z;
        for(i=0; i<4; i++)
        {
            int aa=bu[i][0]+l.x1;
            int bb=bu[i][1]+l.y1;//箱子被推向的坐标(aa,bb)
            if(aa>=0&&aa<n&&bb>=0&&bb<m&&Map1[aa][bb][i]==0&&Map[aa][bb][0]!=1)
            {//当箱子被推的坐标满足在做表范围内,且不是同一方向被推向该点的时候,就能进入循环
                int aa1=l.x1+bu1[i][0];
                int bb1=l.y1+bu1[i][1];
                if(Map[aa1][bb1][0]==1||aa1<0||aa1>=n||bb1<0||bb1>=m)
                    continue;//当箱子的四周为墙或者不在坐标范围内时,就不在向下判断
                Map[l.x1][l.y1][1]=1;//先把地图中箱子的位置标记为墙进行广搜,然后再还原
                int cc=bfs1(l.x2,l.y2,aa1,bb1);
                Map[l.x1][l.y1][1]=0;//还原
                if(cc==-1)//cc==-1说明没有搜到箱子的四周所以不用执行
                    continue;
                r.x1=aa;//箱子被推向的位置的横坐标
                r.y1=bb;//箱子被推向位置的纵坐标
                r.z=l.z+1;//推箱子的步数+1
                r.x2=l.x1;//箱子被推后人的位置就是箱子原来位置的横坐标
                r.y2=l.y1;//箱子被推后人的位置就是箱子位置的纵坐标
                Map1[aa][bb][i]=1;//标记箱子被推后的位置的已经被推过了,i表示从哪那个方向推到该位置的
                v.push(r);
            }
        }
    }
    return -1;
}
int main()
{
    int t,i,j;
    //scanf("%d",&t);
    while(scanf("%d%d",&n,&m)!=EOF)
    {


        for(i=0; i<n; i++)
            for(j=0; j<m; j++)
            {
                scanf("%d",&Map[i][j][0]);
                Map[i][j][1]=Map[i][j][0];//复制地图把除了1以外的都初始化为1
                if(Map[i][j][0]==2)
                {
                    S.x1=i;
                    S.y1=j;
                    S.z=0;
                    Map[i][j][1]=0;
                }
                if(Map[i][j][0]==4)
                {
                    S.x2=i;
                    S.y2=j;
                    Map[i][j][1]=0;
                }
                if(Map[i][j][0]==3)
                {
                    D.x1=i;
                    D.y1=j;
                    Map[i][j][1]=0;
                }
            }
        int aa=bfs();
        if(aa==0)
            printf("-1\n");
        else
        printf("%d\n",aa);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值