推箱子 HDU1254 (bfs)
较难的bfs
有两种方法做
一种双重bfs:
主bfs是箱子 还要通过dfs判断人是否能到箱子后面
用inmap函数的好处。。
箱子要用三位数组来标记 因为箱子可以回到原来到过的地方 因为推的方向不同 (第三位来表示方向)
并且地图无需改变(一些人在结构体里自带一份地图)
这题箱子的位置 对人来是是墙 不可越过 用设置vis2来实现 非常巧妙
用全局flag来代替dfs中的bool 方便很多 也不容易出错
#include<bits/stdc++.h>
using namespace std; int n,m,m1[][],vis[][][],vis2[][];
int sx,sy,ex,ey,rx1,ry1;
int dx[]={,,,-};
int dy[]={,,-,};
int flag=; struct node
{
int x,y,d,rx,ry;
node(int x=,int y=,int d=,int rx=,int ry=):x(x),y(y),d(d),rx(rx),ry(ry){}
}; bool inmap(int a,int b)
{
if(a<||a>n||b<||b>m||m1[a][b]==)
return false;
return true; } void bfs1( int sx, int sy,int ex,int ey)
{ if(sx==ex&&sy==ey) {flag=;return ;}
if(flag==)return;//值得学习
for(int i=;i<;i++)
{ if(vis2[sx+dx[i]][sy+dy[i]]==&&inmap(sx+dx[i],sy+dy[i]))
{
//printf("%d %d \n",sx+dx[i],sy+dy[i]);
vis2[sx+dx[i]][sy+dy[i]]=;
bfs1(sx+dx[i],sy+dy[i],ex,ey); } } } void bfs()
{ memset(vis,,sizeof(vis));
memset(vis2,,sizeof(vis2));
node u(sx,sy,,rx1,ry1);
queue<node>q;
q.push(u); while(!q.empty())
{ u=q.front();q.pop();
// printf("%d %d %d\n",u.x,u.y,u.d);
if(u.x==ex&&u.y==ey){printf("%d\n",u.d);return;} for(int i=;i<;i++)
{
node v(u.x+dx[i],u.y+dy[i],u.d+,u.rx,u.ry);//用自加是错的 if(inmap(u.x-dx[i],u.y-dy[i])&&inmap(v.x,v.y)&&vis[v.x][v.y][i]==)
{
flag=;
memset(vis2,,sizeof(vis2));
vis2[u.rx][u.ry]=;
vis2[u.x][u.y]=;//非常关键!!!箱子也是障碍!!!
bfs1(u.rx,u.ry,u.x-dx[i],u.y-dy[i]); if(flag)
{
vis[v.x][v.y][i]=;
v.rx=u.x-dx[i];
v.ry=u.y-dy[i];
q.push(v);
}
}
}
}
printf("-1\n");return ; }
int main()
{
int cas;scanf("%d",&cas);
while(cas--)
{
scanf("%d%d",&n,&m);
// printf("%d %d\n",n,m);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
scanf("%d",&m1[i][j]);
if(m1[i][j]==){ex=i;ey=j;}
if(m1[i][j]==){sx=i;sy=j;}
if(m1[i][j]==){rx1=i;ry1=j;} }
// printf("%d %d\n",sx,sy);
bfs(); } return ;
}
还有一种方法是一次BFS 优先队列 用四维数组来标记人和箱子的座标 然后人疯狂乱走 如果人走到了箱子上了 就相当于推动了一次
回顾:
一定要用优先队列 不然的话是以人走的步数为基准
还有一定要注意 队列里面的优先级是反的!!!!
#include<iostream>
#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 9
#define inf 0x3f3f3f3f int dx[]={,,,-};
int dy[]={,-,,};
int sx,sy,ex,ey,rx,ry;
int n,m;
int mp[N][N]; bool inmap(int x,int y)
{
return x>=&&x<=n&&y>=&&y<=m;
} struct node
{
int x,y,d,rx,ry;
bool operator <(const node &h)const{
return d>h.d;
}
}; int vis[N][N][N][N]; void bfs()
{
memset(vis,,sizeof vis);
node u,v;
u.x=sx;
u.y=sy;
u.d=;
u.rx=rx;
u.ry=ry;
priority_queue<node>q;
q.push(u);
vis[sx][sy][rx][ry]=;
while(!q.empty())
{
u=q.top();q.pop(); if( mp[u.x][u.y]== ){printf("%d\n",u.d);return ;} for(int i=;i<;i++)
{
v=u;
v.rx+=dx[i];
v.ry+=dy[i];
if( inmap(v.rx,v.ry) &&mp[v.rx][v.ry]!=)
{
if(v.rx==v.x&&v.ry==v.y&& inmap(v.x+dx[i],v.y+dy[i] )&&mp[v.x+dx[i]][v.y+dy[i]]!= )
{
v.x+=dx[i];
v.y+=dy[i];
v.d+=;
}
if(!vis[v.x][v.y][v.rx][v.ry] )
{
q.push(v);
vis[v.x][v.y][v.rx][v.ry]=;
}
}
}
}
printf("-1\n");
} int main()
{
int cas;cin>>cas;
while(cas--)
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
for(int j=;j<=m;j++)
{
scanf("%d",&mp[i][j]);
int t=mp[i][j];
if(t==){rx=i;ry=j;}
if(t==){sx=i;sy=j;}
}
bfs();
}
return ;
}
推箱子 HDU1254 (bfs)的更多相关文章
- 推箱子 (hdu1254)(bfs双重广搜)
推箱子 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission ...
- HDU1254 推箱子(BFS) 2016-07-24 14:24 86人阅读 评论(0) 收藏
推箱子 Problem Description 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推 ...
- HDU 1254 推箱子(BFS)
Problem Description 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不 ...
- HDU 1254 推箱子(BFS加优先队列)
传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1254 推箱子 Time Limit: 2000/1000 MS (Java/Others) Me ...
- 推箱子 hdu1254
推箱子 1 http://acm.hdu.edu.cn/showproblem.php?pid=1254 推箱子 2 http://acm.hzau.edu.cn/problem.php?id=1 ...
- suseoj 1212: 推箱子问题(bfs)
1212: 推箱子问题 时间限制: 1 Sec 内存限制: 128 MB提交: 60 解决: 13[提交][状态][讨论版][命题人:liyuansong] 题目描述 码头仓库是划分为n×m个格子 ...
- AcWing:172. 立体推箱子(bfs)
立体推箱子是一个风靡世界的小游戏. 游戏地图是一个N行M列的矩阵,每个位置可能是硬地(用”.”表示).易碎地面(用”E”表示).禁地(用”#”表示).起点(用”X”表示)或终点(用”O”表示). 你的 ...
- HDU1254:推箱子(bfs+dfs)
传送门 题意 给出一副图 0.空地1.墙2.箱子3.目的地4.人所在的位置 问最少几步能将箱子推到目的地 分析 这道题难度略大(菜鸡),首先用vis[bx][by][mx][my]记录当箱子(bx,b ...
- hdu.1254.推箱子(bfs + 优先队列)
推箱子 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submis ...
随机推荐
- ms sqlserver2008r2 自动备份
日常工作中利用SQL SQLSERVER 2008 的维护计划对数据库进行定期的备份,这样一方面可以对数据库进行备份保证数据安全另一方面也可以减轻对维护人员的负担. 一般对于WEB 服务器进 行维护都 ...
- The provider is not compatible with the version of Oracle client
保留下安装文件夹里的所有文件.然后把我那个很小应用软件(需要访问远程的oracle数据库)放在这个文件夹里.删除一下直接感觉无用的文件,先抽取可 能用不着的文件,保留放在另一个备用的文件夹里,然后运行 ...
- mysql 开源~canal维护相关问题
一 简介:咱们来讨论下canal的一些技巧 二 场景 场景1 canal过滤指定库后,后端java调用读取相关数据时候出现大量的空事务,为何会出现空事务呢,空事务是由于配置了指定的过滤规则,导致了其他 ...
- transform 图标旋转,IE8、IE7不兼容
要将图标旋转,只需使用transform的rotate以及transition即可完成旋转的动画效果.ease 规定慢速开始,然后变快,然后慢速结束的过渡效果; ease-in 规定以慢速开始的过 ...
- jquery选择器最后一个,倒数第二个元素
<div> <p>1</p> <p>2</p> <p>3</p> <p>4</p> < ...
- Web下文件上传下载的路径问题
工程结构
- C#基础系列-反射
1.反射的定义 反射(Reflection),是.Net中获取运行时类型信息的方式.程序集中有关程序及其类型的数据被称为元数据(metadata).程序在运行时,可以查看其它程序集或其本身的元数据.一 ...
- python实战===教你用微信每天给女朋友说晚安
但凡一件事,稍微有些重复.我就考虑怎么样用程序来实现它. 这里给各位程序员朋友分享如何每天给朋友定时微信发送”晚安“,故事,新闻,等等··· ···最好运行在服务器上,这样后台挂起来更方便. 准备: ...
- Linux inotify功能及实现原理【转】
转自:http://blog.csdn.net/myarrow/article/details/7096460 1. inotify主要功能 它是一个内核用于通知用户空间程序文件系统变化的机制. 众所 ...
- MyEclipse2017 CI-7的破解
下载了一个最新版的MyEclipse,网上下载了破解工具,按照步骤完成后破解失败.很纳闷,于是网上查看,说是破解器的版本须与MyEclipse的版本对应,不对应的话,是没有效果的.如我的是CI-7版本 ...