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[][];
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(广度优先搜索)的更多相关文章
- POJ1475 Pushing Boxes(双搜索)
POJ1475 Pushing Boxes 推箱子,#表示墙,B表示箱子的起点,T表示箱子的目标位置,S表示人的起点 本题没有 Special Judge,多解时,先最小化箱子被推动的次数,再最小化 ...
- [poj P1475] Pushing Boxes
[poj P1475] Pushing Boxes Time Limit: 2000MS Memory Limit: 131072K Special Judge Description Ima ...
- 图的广度优先搜索(BFS)
把以前写过的图的广度优先搜索分享给大家(C语言版) #include<stdio.h> #include<stdlib.h> #define MAX_VERTEX_NUM 20 ...
- 广度优先搜索(BFS)
定义 维基百科:https://en.wikipedia.org/wiki/Breadth-first_search 给定图G=(V,E)和一个可识别的源结点s,广度优先搜索对图G中的边进行系统性的探 ...
- 总结A*,Dijkstra,广度优先搜索,深度优先搜索的复杂度比较
广度优先搜索(BFS) 1.将头结点放入队列Q中 2.while Q!=空 u出队 遍历u的邻接表中的每个节点v 将v插入队列中 当使用无向图的邻接表时,复杂度为O(V^2) 当使用有向图的邻接表时, ...
- poj 1475 || zoj 249 Pushing Boxes
http://poj.org/problem?id=1475 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=249 Pushin ...
- ACM题目————图的广度优先搜索
题目描述 图的广度优先搜索类似于树的按层次遍历,即从某个结点开始,先访问该结点,然后访问该结点的所有邻接点,再依次访问各邻接 点的邻接点.如此进行下去,直到所有的结点都访问为止.在该题中,假定所有的结 ...
- SDUT 2141 【TEST】数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历
数据结构实验图论一:基于邻接矩阵的广度优先搜索遍历 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Discuss Problem ...
- 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 ...
随机推荐
- prometheus安装(docker)
参考:https://github.com/songjiayang/prometheus_practice https://github.com/kjanshair/docker-prometheus ...
- 《Linux就该这么学》培训笔记_ch10_使用Apache服务部署静态网站
<Linux就该这么学>培训笔记_ch10_使用Apache服务部署静态网站 文章最后会post上书本的笔记照片. 文章主要内容: 网站服务程序 配置服务文件参数 SELinux安全子系统 ...
- kubernetes学习一:安装及部署第一个Web应用
准备工作 首先准备Kubernets的环境,使用的是centos7.5 关闭防火墙: # systemctl disable firewalld # systemctl stop firewalld ...
- eclipse配置lombok插件
下载lombok-1.16.12.jar包 然后将包添加到eclipse.ini 同级目录下 打开eclipse目录:最后两行添加如下配置: -Xbootclasspath/a:lombok-1.16 ...
- 解决source insight 4.0 不识别.cc文件的问题
Options -> File Type Options, File Filter 中加入,*.cc 参考了C++ Primer Plus第五版中文版 P8 C++实现 源代码的扩展名 UNIX ...
- powershell程序
powershell是一个命令行解释器.它输出一个字符,等待命令行的输入,然后执行这个命令.下面是powershell非常重要的命令:
- spring Boot 学习(六、Spring Boot与分布式)
一.分布式应用在分布式系统中,国内常用zookeeper+dubbo组合,而Spring Boot推荐使用 全栈的Spring,Spring Boot+Spring Cloud 分布式系统: 单一应用 ...
- C# Linq 使用总结
隐式类型匿名类型自动属性初始化器委托泛型泛型委托匿名方法Lambda表达式扩展方法迭代器LINQ System.Linq var arr = new[] { "c", " ...
- 解决老大难疑惑:指针 vs 引用
▶疑问描述 1. 引用reference的本质: 常指针 ——> 什么时候用指针?= 就按Java中的引用变量那样用? ——> 什么时候用引用? ①函数的入参/返回值时 ②T&am ...
- 【MySQL】mysql中的锁机制
一.分类 MySQL的锁机制不同的存储引擎支持不同的锁机制,分为表级锁.行级锁.页面锁.MyISAM和MEMORY存储引擎采用的是表级锁(table-level locking):BDB存储引擎采用的 ...