zoukankan      html  css  js  c++  java
  • Pushing Boxes(广度优先搜索)

    题目传送门

    首先说明我这个代码和lyd的有点不同:可能更加复杂

     既然要求以箱子步数为第一关键字,人的步数为第二关键字,那么我们可以想先找到箱子的最短路径。但单单找到箱子的最短路肯定不行啊,因为有时候不能被推动,怎样确定一条既满足最短又满足可行的箱子路径呢,其实这就是一种有限制的BFS

     对于箱子:

      设现在的位置为x,y,扩展方向为dx,dy,将要到达的下一个位置为x+dx,y+dy

     check它是否可行:

    1.不越界。

    2.之前没有走过。

    3.不能走到“#”上。

    4.人能够从当前站立的位置到达(x-dx,y-dy)。

    诶,对了,第4个条件实际上就是对于人的bfs。


      因此,这就是一个双重bfs。(数据范围r,c<=20可行!)

      那么对于人的bfs,有什么限制条件:当然最重要的不能走到箱子现在的位置(x,y)上

      还有记录路径,每次回溯和逆推。

      嗯,具体细节看代码吧(不想打字了)

    //Pushing Boxes -POJ1475 
    //最长代码 祭 AC  329ms
    //开始没有数组清零WA
    //然后数组开大了,TLE 
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define de system("pause");
    #define re register int
    using namespace std;
    int r,c,ans,ansx,ansy;
    char s[50][50];
    int per[5],box[5];
    int dx[]={-1,1,0,0};
    int dy[]={0,0,-1,1};
    char ren[]={'n','s','w','e'};
    char xiang[]={'N','S','W','E'};
    bool bz[30][30],flag[30][30];
    struct node{
        int x,y,step;
        int man[3];
        node(int xx,int yy,int stepp,int mx,int my)
        {
            x=xx,y=yy,step=stepp;
            man[1]=mx,man[2]=my;
        }
    };
    struct node2{
        int x,y;
        node2(int xx,int yy)
        {
            x=xx;
            y=yy;
        }
    };
    queue<node> q;
    queue<node2> p;
    struct hp{
        int px,py,d;
        int cnt;
        int path[500];
    }fix[30][30],walk[30][30];
    //fix主要记录箱子的路径,walk主要记录人的路径。 inline
    bool bfs(int bx,int by,int aimx,int aimy,int nowx,int nowy) { memset(flag,0,sizeof flag); memset(walk,0,sizeof walk); while(p.size()) p.pop(); p.push(node2(nowx,nowy)); if(nowx==aimx&&nowy==aimy) return 1; flag[nowx][nowy]=1; while(!p.empty()) { node2 now=p.front(); int x=now.x,y=now.y; p.pop(); for(re i=0;i<=3;++i) { int cx=x+dx[i],cy=y+dy[i]; if(cx<1||cx>r||cy<1||cy>c)continue; if(flag[cx][cy])continue; if(s[cx][cy]=='#')continue; if(cx==bx&&cy==by)continue; p.push(node2(cx,cy)); flag[cx][cy]=1; walk[cx][cy].px=x; walk[cx][cy].py=y; walk[cx][cy].d=i; if(cx==aimx&&cy==aimy) { return 1; } } } return 0; } inline bool check(int x,int t1,int y,int t2,int standx,int standy) { if(x+t1<1||x+t1>r||y+t2<1||y+t2>c)return 0; if(bz[x+t1][y+t2]) return 0; if(s[x+t1][y+t2]=='#')return 0; if(bfs(x,y,x-t1,y-t2,standx,standy))//如果人能够移动 { int tx=x-t1,ty=y-t2;//从目标回溯到初位置 while(tx!=standx||ty!=standy) { hp temp=walk[tx][ty]; fix[x+t1][y+t2].path[++fix[x+t1][y+t2].cnt]=walk[tx][ty].d; tx=temp.px; ty=temp.py; }//在这里顺便就把这一次转移路径记录下来 return 1; } return 0; } inline void Bfs() { while(!q.empty()) { node now=q.front(); int x=now.x,y=now.y,step=now.step; int man_x=now.man[1],man_y=now.man[2]; q.pop(); for(re i=0;i<=3;++i) { int cx=x+dx[i],cy=y+dy[i]; if(check(x,dx[i],y,dy[i],man_x,man_y)) { q.push(node(cx,cy,step+1,x,y)); bz[cx][cy]=1; fix[cx][cy].px=x,fix[cx][cy].py=y; fix[cx][cy].d=i; if(s[cx][cy]=='T') { if(step+1<ans) { ans=step+1; ansx=cx,ansy=cy; } } } } } } char shuchu[600]; int rt=0; inline void print() { int num=0; int prx=ansx; int pry=ansy; int tt=0; while((prx!=box[1])||(pry!=box[2])) { hp ne=fix[prx][pry]; shuchu[++num]=xiang[ne.d]; for(re i=1;i<=ne.cnt;++i) { shuchu[++num]=ren[ne.path[i]]; } prx=ne.px; pry=ne.py; } printf("Maze #%d ",++rt); for(re i=num;i>=1;--i) cout<<shuchu[i]; puts(""); } int main() { while(1) { while(q.size())q.pop(); memset(bz,0,sizeof bz); // memset(shuchu,0,sizeof shuchu); memset(fix,0,sizeof fix); // memset(walk,0,sizeof walk); ans=1e6; scanf("%d%d",&r,&c); if(r==0&&c==0)break; for(re i=1;i<=r;++i){ scanf("%s",s[i]+1); for(re j=1;j<=c;++j){ if(s[i][j]=='B')box[1]=i,box[2]=j,bz[i][j]=1; if(s[i][j]=='S')per[1]=i,per[2]=j; } } q.push(node(box[1],box[2],0,per[1],per[2])); Bfs(); if(ans==1e6) { printf("Maze #%d ",++rt); puts("Impossible."); } else print(); puts(""); } return 0; }

    Add/ 

    1.关于POJ的special judge可能有点毒瘤,所以建议按照'N','S','W','E'的方向进行搜索。

    2.数组不要开大了。

    3.输出两个换行......

  • 相关阅读:
    Java多个版本共存
    在RestHighLevelClient中增加用户名密码验证
    request Body 查询
    threadLocal
    thread 中断 interrupt
    Thread 状态和创建方法
    URI Search
    解析器
    基本crud
    第4章 SQL与关系数据库基本操作
  • 原文地址:https://www.cnblogs.com/719666a/p/10518167.html
Copyright © 2011-2022 走看看