HDU 1254 条件过程复杂的寻找最短路
这里一看就是找箱子到终点的最短路
一开始还傻傻的以为人的位置给的很没有意思- -,然后果然错了
没过多久想明白了错误,因为你推箱子并不是你想去哪里推就能去哪推的,首先得考虑人能否过的去,因为可能人被箱子或墙挡住都是可能的
虽然想明白了,但还是写了好久改了好久~~代码能力还是太渣了
利用dfs判定人能否走到所在的位置,bfs搜最短路
dp[i][j][4] 表示在第(i , j)位置上可以用4个方向推箱子,所以又得乘4种状态,最后就不断bfs计算这个dp值就好了
要细心加上耐心哦~~
/*我在这里假设箱子到了终点,我不断将它往回推,看能够推到的地方以及最短步数*/
#include <cstdio>
#include <cstring>
#include <iostream>
#include <queue>
using namespace std;
int dir[][] = {{ , } , { , } , {- , } , { , -}};
int m , n , dp[][][] , a[][] , vis[][][];
int can[][]; //表示人能否到达那个位置 struct Node{
int x , y , pos; //pos表示人的位置,0,1,2,3表示4个方向
Node(int x = , int y = , int pos = ):x(x),y(y),pos(pos){}
}; queue<Node> q;
//判断箱子从x , y按第 i 种方向推能否成立
bool ok(int x , int y , int i)
{
int x1 = x+dir[i][];
int y1 = y+dir[i][];
int x2 = x-dir[i][];
int y2 = y-dir[i][];
if(x1< || x1>m || y1< || y1>n || x2< || x2>m || y2< || y2>n)
return false;
if(a[x1][y1] == || a[x2][y2] == ) return false;
return true;
}
//用dfs搜索人所能走到的位置
void dfs(int x , int y)
{
can[x][y] = ;
for(int i = ; i< ; i++){
int tx = x+dir[i][];
int ty = y+dir[i][];
if(tx>= && tx<=m && ty>= && ty<=n)
if(a[tx][ty]!= && !can[tx][ty]) dfs(tx , ty);
}
}
/*判断人从x1,y1 到x2 , y2这个位置在有箱子位于xbox , ybox遮挡的情况下能否到达*/
bool canTo(int x1 , int y1 , int x2 , int y2 , int xbox , int ybox)
{
int tmp = a[xbox][ybox];
a[xbox][ybox] = ;//暂时将箱子所在位置变成墙 memset(can , , sizeof(can));
dfs(x1 , y1); a[xbox][ybox] = tmp;//还原
if(can[x2][y2] == ) return true;
return false;
} void bfs(int sx , int sy , int pos)
{
dp[sx][sy][pos] = ;
q.push(Node(sx , sy , pos));
while(!q.empty()){
Node u = q.front();
q.pop();
vis[u.x][u.y][u.pos] = ;
for(int i = ; i< ; i++){
//人当前的位置
int curx = u.x + dir[u.pos][];
int cury = u.y + dir[u.pos][];
//人将要走到的位置
int nextx = u.x - dir[i][];
int nexty = u.y - dir[i][];
//先判定人即将到达的方向是否合理
if(nextx < || nextx > m || nexty < || nexty>n) continue;
//再判定人能否到达推箱子所在的位置
if(!canTo(curx , cury , nextx , nexty , u.x , u.y)) continue; //如果箱子可以移动,那就记录移动时人所在的方向p
int p = (i+) % ; //人是在箱子的反方向,这里可以这样用是因为dir中的方向设置的对称
Node v = Node(u.x+dir[i][] , u.y+dir[i][] , p); if(ok(u.x , u.y , i)){
// cout<<"pos: "<<v.x<<" "<<v.y<<" "<<dp[v.x][v.y]<<endl;
if(dp[v.x][v.y][v.pos] > dp[u.x][u.y][u.pos] + ){
dp[v.x][v.y][v.pos] = dp[u.x][u.y][u.pos] + ;
if(!vis[v.x][v.y][v.pos]){
vis[v.x][v.y][v.pos] = ;
q.push(v);
}
}
}
}
}
} int main()
{
// freopen("a.in" , "r" , stdin);
int T;
scanf("%d" , &T);
while (T--){
scanf("%d%d" , &m , &n);
Node tmp1 , tmp2 , tmp3; //用来记录终点的位置,和箱子的位置和人的位置
for(int i = ; i<=m ; i++)
for(int j = ; j<=n ; j++){
scanf("%d" , &a[i][j]);
if(a[i][j] == ) tmp1 = Node(i , j , );
if(a[i][j] == ) tmp2 = Node(i , j , );
if(a[i][j] == ) tmp3 = Node(i , j , );
} memset(dp , 0x3f , sizeof(dp));
memset(vis , , sizeof(vis)); memset(can , , sizeof(can));
a[tmp2.x][tmp2.y] = ;
dfs(tmp3.x , tmp3.y);
a[tmp2.x][tmp2.y] = ;
//看最开始人能从哪个位置开始推
for(int i = ; i< ; i++){
int tx = tmp2.x + dir[i][];
int ty = tmp2.y + dir[i][];
if(tx >= && tx <= m && ty >= && ty <= n)
if(can[tx][ty]){
// cout<<"haha: "<<tx<<" " <<ty <<" "<<i<<endl;
bfs(tmp2.x , tmp2.y , i);
}
} int minn = 0x3f3f3f3f;
for(int i = ; i< ; i++){
minn = min(minn , dp[tmp1.x][tmp1.y][i]);
}
if(minn < 0x3f3f3f3f) printf("%d\n" , minn);
else printf("-1\n");
}
return ;
}
HDU 1254 条件过程复杂的寻找最短路的更多相关文章
- HDU 5980 Find Small A(寻找小A)
p.MsoNormal { margin: 0pt; margin-bottom: .0001pt; text-align: justify; font-family: Calibri; font-s ...
- O - 推箱子 HDU - 1254(bfs_box + bfs_man)
O - 推箱子 HDU - 1254 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能 ...
- HDU 1254
http://acm.hdu.edu.cn/showproblem.php?pid=1254 暴搜,状态是四维的(箱子和人的坐标),向一个方向推箱子还要判断人能否走到推的位置,1A #include ...
- HDU 1254 推箱子 BFS
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=1254 题目分析: 做这道题,感觉挺简单的,做着做着就错了20次, 我也是醉了, WA到吐的节奏啊! 思 ...
- HDU 1254 推箱子游戏(搞了一下午。。。)
中文题目:http://acm.hdu.edu.cn/showproblem.php?pid=1254 一开始常规的人用来做主导,想着想着不对劲,其实是箱子为主导,人只是箱子能否推进的一个判断. 可以 ...
- hdu 1254 推箱子(搜索)
我写的第一道感觉比较难的搜索 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1254 首先要推箱子的话要满足人能够在箱子旁边,而且人的对面也是可通的. ...
- hdu 1254(两个BFS) 推箱子
http://acm.hdu.edu.cn/showproblem.php?pid=1254 首先,要判断人是不是可以从4到达箱子的位置2,而且不止判断一次,因为推动箱子一步后,人的位置也会改变,所以 ...
- HDU 1254 推箱子(BFS加优先队列)
传送门: http://acm.hdu.edu.cn/showproblem.php?pid=1254 推箱子 Time Limit: 2000/1000 MS (Java/Others) Me ...
- hdu - 1254 推箱子 (bfs+bfs)
http://acm.hdu.edu.cn/showproblem.php?pid=1254 题目意思很简单,只要思路对就好. 首先考虑搬运工能否到达推箱子的那个点,这个可以根据箱子前进方向得出搬运工 ...
随机推荐
- bzoj 3390: [Usaco2004 Dec]Bad Cowtractors牛的报复【最大生成树】
裸的最大生成树,注意判不连通情况 #include<iostream> #include<cstdio> #include<algorithm> using nam ...
- bzoj 1672: [Usaco2005 Dec]Cleaning Shifts 清理牛棚【dp+线段树】
设f[i]为i时刻最小花费 把牛按l升序排列,每头牛能用f[l[i]-1]+c[i]更新(l[i],r[i])的区间min,所以用线段树维护f,用排完序的每头牛来更新,最后查询E点即可 #includ ...
- AutoCAD C# 利用反射导出所注册的命令
主函数导出某一程序集AutoCAD 注册命令 /// <summary> ///提取所有的命令 /// </summary> /// <param name=" ...
- Python基础类型(一) int 整型
Python算术运算符 以下假设变量: a=10,b=20: 运算符 描述 实例 + 加 - 两个对象相加 a + b 输出结果 30 - 减 - 得到负数或是一个数减去另一个数 a - b 输出结果 ...
- C语言小项目-基于TCP协议和SOCKET编程的网络通信系统
1.1 功能结构图 网络通信系统一共由4个模块组成,分别是点对点客户端.点对点服务端.服务器中转服务端.服务器中转客户端.这4个模块是成对使用的,点对点客户端和点对点服务端一起使用,服务器中转服务 ...
- vue2.0之60s验证码发送
快速的说下我的60s经历不管移动还是pc端的登录都需要发送验证信息,那么我们熟悉的那个验证按钮就不可少了.首先,我们都知道的一些基本功能.1.验证账号输入的格式正确与否(减少传递基本的错误信息)2.@ ...
- 关于加减和es6
console.log(1+ "2"+"2"); //对于加法来说,如果只有一个操作数是字符串,则将另一个操作数也转换为字符串,然后将两者拼接,为122 c ...
- Android Studio Activity Intent 闪退崩溃 Toolbar
今天写登录注册页面,点击登录页面的“注册”按钮后软件突然崩溃,直接闪退,因为是新手,只能去网上搜.虽然网上解决方法众多,但也没找到可行的.想起来可以看Logcat,马上重新运行应用,查看崩溃时的日志, ...
- (求助)对某一颜色,设置透明度 alpha 后,其他使用该颜色的地方 受到影响!!!!原因未知
对某一颜色,设置透明度 alpha 后,其他使用该颜色的地方 受到影响!!!!原因未知,有谁碰到过这样的问题?????? 测试了以下三款手机,结果如下: 1.android 4.4.2: 不受影响 2 ...
- 动态排序JavaBean
Java中如果对对象排序可以考虑实现Comparable接口,但是需要排序的属性一旦指定就不能再修改.BeanUtils组件提供了对JavaBean动态排序的支持,即可以在运行时指定排序的属性.实例运 ...