POJ1475 Pushing Boxes(双搜索)
POJ1475 Pushing Boxes
推箱子,#表示墙,B表示箱子的起点,T表示箱子的目标位置,S表示人的起点
本题没有 Special Judge,多解时,先最小化箱子被推动的次数,再最小化人移动的步数。若仍有多条路线,则按照N、S、W、E的顺序优先选择箱子的移动方向(即先上下推,再左右推)。在此前提下,再按照n、s、w、e的顺序优先选择人的移动方向(即先上下动,再左右动)。
- 每个阶段的状态包括人的位置,箱子的位置,由于每次在移动箱子之后,人的位置一定位于箱子之前的位置,所以可以将每次箱子刚刚移动后,箱子与人的位置的状态打包在一起,bfs中对于取出的队头,枚举箱子的下一个位置,然后再用一个bfs求出人由现在的位置到应该在的位置的最短步数即可
- Impossible后面没打'.',调了一上午qwq
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
#include <queue>
#include <iostream>
#include <cmath>
using namespace std; #define N 26
#define res int
#define inf 0x3f3f3f3f const int dx[]={-,,,},dy[]={,,-,};
const char A[]={'N','S','W','E'},B[]={'n','s','w','e'};
int n,m;
char s[][]; string tmp;
struct node {
int x,y,px,py;
string ans;
}; inline bool valid(int x,int y){
return (x>= && x<=n && y>= && y<=m && s[x][y]!='#');
} bool bfs2(node a,node b)
{
tmp="";
node st;
st.x=a.px;
st.y=a.py;
st.ans="";//人的初始位置
queue<node> q;
q.push(st);
bool v[][];
memset(v,,sizeof(v));
while(q.size())
{
node now=q.front(); q.pop();
if(now.x==a.x && now.y==a.y)
{ tmp=now.ans; return true; }
for(res k= ; k< ; k++)
{
node nxt;
nxt.x=now.x+dx[k];
nxt.y=now.y+dy[k];
if(!valid(nxt.x,nxt.y)||v[nxt.x][nxt.y]) continue;
if(nxt.x==b.x && nxt.y==b.y) continue;
v[nxt.x][nxt.y]=;
nxt.ans=now.ans+B[k];
q.push(nxt);
}
}
return false;
}
node st;
string bfs1()
{
st.x=st.y=st.px=st.py=-;
st.ans="";
for(res i= ; i<=n ; i++)
for(res j= ; j<=m ; j++)
if(s[i][j]=='B')
st.x=i,st.y=j,s[i][j]='.';
else if(s[i][j]=='S')
st.px=i,st.py=j,s[i][j]='.';
queue<node> q;
int v[][][];
memset(v,,sizeof(v));
q.push(st);
string ans="Impossible.";
int cnt_box=inf,cnt_man=inf;
while(q.size())
{
node now=q.front(); q.pop();
if(s[now.x][now.y]=='T')
{
int cntb();
for(res i= ; i<now.ans.length() ; i++)
if(now.ans[i]>'A' && now.ans[i]<'Z') cntb++;
if(cntb<cnt_box || (cntb==cnt_box&& now.ans.length()-cntb<cnt_man))
cnt_box=cntb,cnt_man=now.ans.length()-cntb,ans=now.ans;
continue;
}
for(res k= ; k< ; k++)
{
node nxt; nxt.x=now.x+dx[k]; nxt.y=now.y+dy[k];
if(!valid(nxt.x,nxt.y) || v[nxt.x][nxt.y][k]) continue; node pre=now;
if(k==) pre.y=now.y-;
else if(k==) pre.y=now.y+;
else if(k==) pre.x=now.x-;
else pre.x=now.x+;//人的移动,此处x,y表示目标位置
v[nxt.x][nxt.y][k]=;
if(!valid(pre.x,pre.y) || !bfs2(pre,now)) continue;
nxt.ans=now.ans+tmp;
nxt.ans+=A[k];
nxt.px=now.x;
nxt.py=now.y;
q.push(nxt);
}
}
return ans;
} int main()
{
int Case();
while(scanf("%d %d",&n,&m)&&n&&m)
{
Case++;
for(res i= ; i<=n ; i++) cin>>(s[i]+);
cout<<"Maze #"<<Case<<endl;
cout<<bfs1()<<endl<<endl;
}
return ;
}
POJ1475 Pushing Boxes(双搜索)的更多相关文章
- poj1475 Pushing Boxes[双重BFS(毒瘤搜索题)]
地址. 很重要的搜索题.★★★ 吐槽:算是写过的一道码量比较大的搜索题了,细节多,还比较毒瘤.虽然是一遍AC的,其实我提前偷了大数据,但是思路还是想了好长时间,照理说想了半小时出不来,我就会翻题解,但 ...
- POJ1475(Pushing Boxes)--bbffss
题目在这里 题目一看完就忙着回忆童年了.推箱子的游戏. 假设只有一个箱子.游戏在一个R行C列的由单位格子组成的区域中进行,每一步, 你可以移动到相邻的四个格子中的一个,前提是那个格子是空的:或者,如果 ...
- poj1475 -- Pushing Boxes
这道题其实挺有趣 的,这让我想起小时候诺基亚手机上的推箱子游戏(虽然一点也不好玩) (英文不好-->) 题意翻译: 初始人(S),箱子(B),目的地(T)用人把箱子推到 T最小步数及其路径(满 ...
- POJ-1475 Pushing Boxes (BFS+优先队列)
Description Imagine you are standing inside a two-dimensional maze composed of square cells which ma ...
- poj1475 Pushing Boxes(BFS)
题目链接 http://poj.org/problem?id=1475 题意 推箱子游戏.输入迷宫.箱子的位置.人的位置.目标位置,求人是否能把箱子推到目标位置,若能则输出推的最少的路径,如果有多条步 ...
- POJ1475 Pushing Boxes(BFS套BFS)
描述 Imagine you are standing inside a two-dimensional maze composed of square cells which may or may ...
- POJ1475 Pushing Boxes 华丽丽的双重BFS
woc累死了写了两个半小时...就是BFS?我太菜了... 刚开始以为让人预先跑一遍BFS,然后一会儿取两节加起来就好了,结果发现求出来的最短路(就是这个意思)会因箱子的移动而变化....我死了QWQ ...
- Pushing Boxes(广度优先搜索)
题目传送门 首先说明我这个代码和lyd的有点不同:可能更加复杂 既然要求以箱子步数为第一关键字,人的步数为第二关键字,那么我们可以想先找到箱子的最短路径.但单单找到箱子的最短路肯定不行啊,因为有时候不 ...
- [poj P1475] Pushing Boxes
[poj P1475] Pushing Boxes Time Limit: 2000MS Memory Limit: 131072K Special Judge Description Ima ...
随机推荐
- KVC的底层实现原理
KVC是OC特有的,本质是在运行时动态的给对象发送setValue:forKey 消息,设置数值 -调用super.init 保证对象已经被创建完成 .当给对象发送setValue:forKey 消息 ...
- Opencv Convex Hull (凸包)
#include <iostream>#include <opencv2/opencv.hpp> using namespace std;using namespace cv; ...
- sqlserver计算日期
在网上找到的一篇文章,相当不错哦O(∩_∩)O~ 这是计算一个月第一天的SQL 脚本: SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0) --当月的第一 ...
- 在centos6.3_64bit 上的GO语言开发环境搭建
1.下载go安装包 http://golang.org/ go1.2.linux-amd64.tar.gz 2.配置环境变量 3.编写helloworld package main import ...
- Mule ESB 安装基本配置要求
Hardware Requirements* 2GHz, dual-core CPU, or 2 virtual CPUs in virtualized environments 2GB of RAM ...
- Linux分区挂载点介绍
一.Linux分区挂载点介绍 Linux分区挂载点介绍,推荐容量仅供参考不是绝对,跟各系统用途以及硬盘空间配额等因素实际调整: 分区类型 介绍 备注 /boot 启动分区 一般设置100M-200M, ...
- SQLSERVER Tempdb的作用及优化
tempdb 系统数据库是可供连接到 SQL Server 实例的所有用户使用的全局资源.tempdb 数据库用于存储下列对象:用户对象.内部对象和版本存储区. 用户对象 用户对象由用户显式创建.这些 ...
- Openssl rand命令
一.简介 rand命令用来产生伪随机字节,随机数字产生器需要一个seed,在没有/dev/srandom系统下的解决方法是自己做一个~/.rnd文件 二.语法 openssl rand [-out f ...
- code4511 信息传递
寻找最小环 #include <cstdio> #include <cstring> #include <iostream> using namespace std ...
- [GO]多任务的资源竞争问题
package main import ( "fmt" "time" ) func Printer(s string) { for _, data := ran ...