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];
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\n",++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\n",++rt);
            puts("Impossible.");
        }
        else print();
        puts("");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/719666a/p/10518167.html

时间: 2024-10-10 14:46:42

Pushing Boxes(广度优先搜索)的相关文章

【15.4.1 Pushing Boxes】双重bfs

[15.4.1 Pushing Boxes] 想象您正站在一个二维的迷宫中,迷宫由是正方形的方格组成,这些方格可能被岩石阻塞,也可能没有.您可以向北,南,东或西一步移到下一个方格.这些移动被称为行走(walk). 在一个空方格中放置了一个箱子,您可以挨着箱子站着,然后按这个方向推动这个箱子,这个箱子就可以被移动到一个临近的位置.这样的一个移动被称为推(push).除了推以外,箱子不可能用其他的方法被移动,这就意味着如果您把箱子推到一个角落,您就永远不能再把它从角落中推出. 一个空格被标识为目标空

无向图的深度优先与广度优先搜索代码实现

图采用了邻接表的形式储存. 带不带权都无所谓的 深度优先搜索 Depth First Search 道理和树的先序遍历差不多,把将要访问的点入栈,然后从栈里取点进行访问. 由于这只是类中的一个成员函数,有些被调用的函数的具体代码将会在文章最后补上 ,但是函数功能看注释就好了 1 //深度优先 2 void GraphAdjacencyListWeight::DFSAdvanced(int StartVertex) { 3 int *visited = new int[VertexNumber];

SDUT 2141 【TEST】数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历

数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem Description 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列.(同一个结点的同层邻接点,节点编号小的优先遍历) Input 输入第一行为整数n(0< n <100),表示数据的组数.对于每组数据,第一行是三个整数k,m,t(0<

poj 1475 Pushing Boxes

http://poj.org/problem?id=1475 Pushing Boxes Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 4662   Accepted: 1608   Special Judge Description Imagine you are standing inside a two-dimensional maze composed of square cells which may or

HDU 1475 Pushing Boxes

Pushing Boxes Time Limit: 2000ms Memory Limit: 131072KB This problem will be judged on PKU. Original ID: 147564-bit integer IO format: %lld      Java class name: Main Special Judge Imagine you are standing inside a two-dimensional maze composed of sq

数据结构实验之图论二:基于邻接表的广度优先搜索遍历

数据结构实验之图论二:基于邻接表的广度优先搜索遍历 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 给定一个无向连通图,顶点编号从0到n-1,用广度优先搜索(BFS)遍历,输出从某个顶点出发的遍历序列.(同一个结点的同层邻接点,节点编号小的优先遍历) 输入 输入第一行为整数n(0< n <100),表示数据的组数. 对于每组数据,第一行是三个整数k,m,t(0<k<100,0<m<(k-1)*k/2,

图算法系列-深度优先搜索与广度优先搜索

2.深度优先搜索 为了访问一个顶点,我们将它标记为已经访问过,然后递归的访问所有与子邻接的并且尚未标记的顶点,这就是深度优先搜索(DFS),DFS常用于解决路径问题. 比如下面的连通图,我们从顶点0开始对图进行探索 下面这个图显示了DFS处理时的递归调用树. DFS可以解决的问题:1)环检测:一个图中有环吗?该图是森林吗?2)简单路径:给定两个顶点,是否存在一条连接他们的路径3)简单连通性:无论何时使用DFS,都可以在线性时间内确定一个图是否连通4)顶点搜索:在给定顶点所在的同一个连通分量中有多

图的遍历(深度优先与广度优先搜索两种方案)

1.图的遍历--深度优先搜索 import java.util.Scanner ; public class Map{ static int n ; static int m ; static int[] book ; static int[][] e ; public static void mapDfs(int cur){ //深度优先搜索思想核心: System.out.print(cur + " ") ; for (int i=1;i<=n;i++) { if (e[cu

矩阵图中的广度优先搜索

经常会有类似的题目,如迷宫问题,在一个矩阵图中给定出发点和目标点,每次只能上下左右移动,求到目标点的最短走法,或者说是一共有多少种走法. 思路其实很简单,深搜.广搜.相对比较而言,广度优先搜索更加实用于求最短的走法(步数) 在矩阵图中的广搜需要注意一下几点. 1.确定每步的走法:不同题的走法可能不同,每次搜索时将走法保存在数组中. 2.确定初始状态 往往注意刚开始得起点(i,j)必须把MAP(i,j)改变为 -1(或者其他的),栈中第一个元素即为初始状态 3.保存状态.这点很重要.需要用数组或者