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;
}
發佈了64 篇原創文章 · 獲贊 2 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章