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(双搜索)的更多相关文章

  1. poj1475 Pushing Boxes[双重BFS(毒瘤搜索题)]

    地址. 很重要的搜索题.★★★ 吐槽:算是写过的一道码量比较大的搜索题了,细节多,还比较毒瘤.虽然是一遍AC的,其实我提前偷了大数据,但是思路还是想了好长时间,照理说想了半小时出不来,我就会翻题解,但 ...

  2. POJ1475(Pushing Boxes)--bbffss

    题目在这里 题目一看完就忙着回忆童年了.推箱子的游戏. 假设只有一个箱子.游戏在一个R行C列的由单位格子组成的区域中进行,每一步, 你可以移动到相邻的四个格子中的一个,前提是那个格子是空的:或者,如果 ...

  3. poj1475 -- Pushing Boxes

    这道题其实挺有趣 的,这让我想起小时候诺基亚手机上的推箱子游戏(虽然一点也不好玩) (英文不好-->)  题意翻译: 初始人(S),箱子(B),目的地(T)用人把箱子推到 T最小步数及其路径(满 ...

  4. POJ-1475 Pushing Boxes (BFS+优先队列)

    Description Imagine you are standing inside a two-dimensional maze composed of square cells which ma ...

  5. poj1475 Pushing Boxes(BFS)

    题目链接 http://poj.org/problem?id=1475 题意 推箱子游戏.输入迷宫.箱子的位置.人的位置.目标位置,求人是否能把箱子推到目标位置,若能则输出推的最少的路径,如果有多条步 ...

  6. POJ1475 Pushing Boxes(BFS套BFS)

    描述 Imagine you are standing inside a two-dimensional maze composed of square cells which may or may ...

  7. POJ1475 Pushing Boxes 华丽丽的双重BFS

    woc累死了写了两个半小时...就是BFS?我太菜了... 刚开始以为让人预先跑一遍BFS,然后一会儿取两节加起来就好了,结果发现求出来的最短路(就是这个意思)会因箱子的移动而变化....我死了QWQ ...

  8. Pushing Boxes(广度优先搜索)

    题目传送门 首先说明我这个代码和lyd的有点不同:可能更加复杂 既然要求以箱子步数为第一关键字,人的步数为第二关键字,那么我们可以想先找到箱子的最短路径.但单单找到箱子的最短路肯定不行啊,因为有时候不 ...

  9. [poj P1475] Pushing Boxes

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

随机推荐

  1. KVC的底层实现原理

    KVC是OC特有的,本质是在运行时动态的给对象发送setValue:forKey 消息,设置数值 -调用super.init 保证对象已经被创建完成 .当给对象发送setValue:forKey 消息 ...

  2. Opencv Convex Hull (凸包)

    #include <iostream>#include <opencv2/opencv.hpp> using namespace std;using namespace cv; ...

  3. sqlserver计算日期

    在网上找到的一篇文章,相当不错哦O(∩_∩)O~ 这是计算一个月第一天的SQL 脚本:  SELECT DATEADD(mm, DATEDIFF(mm,0,getdate()), 0) --当月的第一 ...

  4. 在centos6.3_64bit 上的GO语言开发环境搭建

    1.下载go安装包 http://golang.org/ go1.2.linux-amd64.tar.gz   2.配置环境变量 3.编写helloworld package main import ...

  5. Mule ESB 安装基本配置要求

    Hardware Requirements* 2GHz, dual-core CPU, or 2 virtual CPUs in virtualized environments 2GB of RAM ...

  6. Linux分区挂载点介绍

    一.Linux分区挂载点介绍 Linux分区挂载点介绍,推荐容量仅供参考不是绝对,跟各系统用途以及硬盘空间配额等因素实际调整: 分区类型 介绍 备注 /boot 启动分区 一般设置100M-200M, ...

  7. SQLSERVER Tempdb的作用及优化

    tempdb 系统数据库是可供连接到 SQL Server 实例的所有用户使用的全局资源.tempdb 数据库用于存储下列对象:用户对象.内部对象和版本存储区. 用户对象 用户对象由用户显式创建.这些 ...

  8. Openssl rand命令

    一.简介 rand命令用来产生伪随机字节,随机数字产生器需要一个seed,在没有/dev/srandom系统下的解决方法是自己做一个~/.rnd文件 二.语法 openssl rand [-out f ...

  9. code4511 信息传递

    寻找最小环 #include <cstdio> #include <cstring> #include <iostream> using namespace std ...

  10. [GO]多任务的资源竞争问题

    package main import ( "fmt" "time" ) func Printer(s string) { for _, data := ran ...