题目传送门

首先说明我这个代码和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[][];
int per[],box[];
int dx[]={-,,,};
int dy[]={,,-,};
char ren[]={'n','s','w','e'};
char xiang[]={'N','S','W','E'};
bool bz[][],flag[][];
struct node{
int x,y,step;
int man[];
node(int xx,int yy,int stepp,int mx,int my)
{
x=xx,y=yy,step=stepp;
man[]=mx,man[]=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[];
}fix[][],walk[][];
//fix主要记录箱子的路径,walk主要记录人的路径。
inline bool bfs(int bx,int by,int aimx,int aimy,int nowx,int nowy)
{
memset(flag,,sizeof flag);
memset(walk,,sizeof walk);
while(p.size()) p.pop();
p.push(node2(nowx,nowy));
if(nowx==aimx&&nowy==aimy) return ;
flag[nowx][nowy]=;
while(!p.empty())
{
node2 now=p.front();
int x=now.x,y=now.y;
p.pop();
for(re i=;i<=;++i)
{
int cx=x+dx[i],cy=y+dy[i];
if(cx<||cx>r||cy<||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]=;
walk[cx][cy].px=x;
walk[cx][cy].py=y;
walk[cx][cy].d=i;
if(cx==aimx&&cy==aimy)
{
return ;
}
}
}
return ;
}
inline bool check(int x,int t1,int y,int t2,int standx,int standy)
{
if(x+t1<||x+t1>r||y+t2<||y+t2>c)return ;
if(bz[x+t1][y+t2]) return ;
if(s[x+t1][y+t2]=='#')return ;
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 ;
}
return ;
}
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[],man_y=now.man[];
q.pop();
for(re i=;i<=;++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+,x,y));
bz[cx][cy]=;
fix[cx][cy].px=x,fix[cx][cy].py=y;
fix[cx][cy].d=i;
if(s[cx][cy]=='T')
{
if(step+<ans)
{
ans=step+;
ansx=cx,ansy=cy;
}
}
}
}
}
} char shuchu[];
int rt=;
inline void print()
{
int num=;
int prx=ansx;
int pry=ansy;
int tt=;
while((prx!=box[])||(pry!=box[]))
{
hp ne=fix[prx][pry];
shuchu[++num]=xiang[ne.d];
for(re i=;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>=;--i) cout<<shuchu[i];
puts("");
}
int main()
{
while()
{
while(q.size())q.pop();
memset(bz,,sizeof bz);
// memset(shuchu,0,sizeof shuchu);
memset(fix,,sizeof fix);
// memset(walk,0,sizeof walk);
ans=1e6;
scanf("%d%d",&r,&c);
if(r==&&c==)break;
for(re i=;i<=r;++i){
scanf("%s",s[i]+);
for(re j=;j<=c;++j){
if(s[i][j]=='B')box[]=i,box[]=j,bz[i][j]=;
if(s[i][j]=='S')per[]=i,per[]=j;
}
}
q.push(node(box[],box[],,per[],per[]));
Bfs();
if(ans==1e6)
{
printf("Maze #%d\n",++rt);
puts("Impossible.");
}
else print();
puts("");
}
return ;
}

Add/

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

2.数组不要开大了。

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

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

  1. POJ1475 Pushing Boxes(双搜索)

    POJ1475 Pushing Boxes  推箱子,#表示墙,B表示箱子的起点,T表示箱子的目标位置,S表示人的起点 本题没有 Special Judge,多解时,先最小化箱子被推动的次数,再最小化 ...

  2. [poj P1475] Pushing Boxes

    [poj P1475] Pushing Boxes Time Limit: 2000MS   Memory Limit: 131072K   Special Judge Description Ima ...

  3. 图的广度优先搜索(BFS)

    把以前写过的图的广度优先搜索分享给大家(C语言版) #include<stdio.h> #include<stdlib.h> #define MAX_VERTEX_NUM 20 ...

  4. 广度优先搜索(BFS)

    定义 维基百科:https://en.wikipedia.org/wiki/Breadth-first_search 给定图G=(V,E)和一个可识别的源结点s,广度优先搜索对图G中的边进行系统性的探 ...

  5. 总结A*,Dijkstra,广度优先搜索,深度优先搜索的复杂度比较

    广度优先搜索(BFS) 1.将头结点放入队列Q中 2.while Q!=空 u出队 遍历u的邻接表中的每个节点v 将v插入队列中 当使用无向图的邻接表时,复杂度为O(V^2) 当使用有向图的邻接表时, ...

  6. poj 1475 || zoj 249 Pushing Boxes

    http://poj.org/problem?id=1475 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=249 Pushin ...

  7. ACM题目————图的广度优先搜索

    题目描述 图的广度优先搜索类似于树的按层次遍历,即从某个结点开始,先访问该结点,然后访问该结点的所有邻接点,再依次访问各邻接 点的邻接点.如此进行下去,直到所有的结点都访问为止.在该题中,假定所有的结 ...

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

    数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem ...

  9. HDU 1312 Red and Black DFS(深度优先搜索) 和 BFS(广度优先搜索)

    Red and Black Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...

随机推荐

  1. Idea 进行断点调试的 快捷键

    快捷键 功能描述F8 单步调试,不进入函数内部F7 单步调试,进入函数内部Shift+F7 选择要进入的函数Shift+F8 跳出函数Alt+F9 运行到断点Alt+F8 执行表达式查看结果F9 继续 ...

  2. Alpha冲刺——测试篇

    课程信息 课程 软件工程1916|W(福州大学) 团队名称 修!咻咻! 作业要求 项目Alpha冲刺 团队目标 切实可行的计算机协会维修预约平台 团队信息 队员学号 队员姓名 个人博客地址 备注 22 ...

  3. python mysqldb批量执行语句executemany

    MySQLdb提供了两个执行语句的方法,一个是execute(),另一个是executemany() execute(sql) 可接受一条语句从而执行 executemany(templet,args ...

  4. 【leet-code】接雨水

    给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 ...

  5. Flink 源码解析 —— 项目结构一览

    Flink 源码项目结构一览 https://t.zsxq.com/MNfAYne 博客 1.Flink 从0到1学习 -- Apache Flink 介绍 2.Flink 从0到1学习 -- Mac ...

  6. Mysql系列(四) —— MySQL的Charset和Collation

    本文转载自:再见乱码:5分钟读懂MySQL字符集设置 一.内容概述 在MySQL的使用过程中,了解字符集.字符序的概念,以及不同设置对数据存储.比较的影响非常重要.不少同学在日常工作中遇到的" ...

  7. (7)ASP.NET Core 中的错误处理

    1.前言 ASP.NET Core处理错误环境区分为两种:开发环境和非开发环境.●开发环境:开发人员异常页.●非开发环境:异常处理程序页.状态代码页.在Startup.Configure方法里面我们会 ...

  8. java中String字符串

    一.定义String字符串 String字符串和char字符不同,char使用单引号,只能表示一个字符,字符串就是一段文本.String是个类.这个类使用final修饰,所以这个类是不可以继承扩充和修 ...

  9. .net list转树状结构

    主要的方法 /// <summary> /// 转化成树结构 /// </summary> /// <param name="menuList"> ...

  10. Gearman介绍、原理分析、实践改进

    gearman是什么? 它是分布式的程序调用框架,可完成跨语言的相互调用,适合在后台运行工作任务.最初是2005年perl版本,2008年发布C/C++版本.目前大部分源码都是(Gearmand服务j ...