hdu 1254 推箱子 BFS
2016-07-12 20:09
330 查看
hdu 1254 推箱子 BFS[含测试数据]
题目链接: Here!思路:每次箱子移动之前,肯定都是人先到达箱子相邻的位置上,然后推动箱子移动一步。比如:箱子现在的位置是(x,y),如果箱子需要向(1,0)方向移动,即箱子要移动到(x+1,y),那么肯定需要先让人移动到(x-1,y)的位置上。如果
这样每次箱子移动一步之前,就需要检查人是不是能够到达与之相邻的位置。
然后需要注意的几点:
BFS需要保存的状态:
对于人的移动,只需要保存当前移动到的坐标;
对于箱子的移动,则需要保存当前箱子移动到的坐标与移动的步数, 还有一个就是当前人的位置;
例如下面的第三组数据,需要注意的是对于箱子的移动的vis数组要开三维的,因为箱子可能经过同一个点多次。
测试数据:
4
5 5
3 0 1 0 0
1 0 1 4 0
0 0 1 0 0
1 0 2 0 0
0 0 0 0 0
5 5
0 3 0 0 0
1 0 1 4 0
0 0 1 0 0
1 0 2 0 0
0 0 0 0 0
5 5
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 1 2 1 1
4 0 3 0 0
7 4
0 0 0 0
0 0 1 0
0 2 0 3
1 4 1 0
1 0 1 0
1 0 1 0
1 0 0 0
答案应该是:-1 4 5 2
#include <map> #include <vector> #include <queue> #include <cmath> #include <cstdio> #include <string> #include <cstring> #include <iomanip> #include <iostream> #include <algorithm> using namespace std; //#pragma comment(linker, "/STACK:1024000000,1024000000") #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w",stdout) #define CASE(T) for(scanf("%d",&T);T--;) #define fst first #define snd second #define lson l, mid, rt << 1 #define rson mid+1, r, rt << 1 | 1 const int MAXN = 7 + 5; //const double eps = 1e-6; const int DIR[][2] = { {0, 1}, {0, -1}, {1, 0}, { -1, 0} }; struct NodeP { int x, y; } cur_p, rear_p; struct NodeB : public NodeP { int step; NodeP p_pos; } cur_b, rear_b; int T, N, M; int Gx, Gy; int G[MAXN][MAXN]; bool vis_p[MAXN][MAXN]; bool vis_b[MAXN][MAXN][4]; queue<NodeP> QP; queue<NodeB> QB; inline bool outRange(int x, int y) { return x < 0 || y < 0 || x >= N || y >= M; } bool BFS_P(int Px, int Py) { if(outRange(Px, Py)) return false; int ret = false; memset(vis_p, false, sizeof(vis_p)); vis_p[cur_p.x][cur_p.y] = true; QP.push(cur_p); while(!QP.empty()) { cur_p = QP.front(); QP.pop(); if(ret) continue; if(cur_p.x == Px && cur_p.y == Py) { ret = true; continue; } for(int i = 0; i < 4; i ++) { rear_p.x = cur_p.x + DIR[i][0]; rear_p.y = cur_p.y + DIR[i][1]; if(outRange(rear_p.x, rear_p.y)) continue; if(vis_p[rear_p.x][rear_p.y]) continue; if(G[rear_p.x][rear_p.y] == 1 || (rear_p.x == cur_b.x && rear_p.y == cur_b.y)) continue; vis_p[rear_p.x][rear_p.y] = true; QP.push(rear_p); } } return ret; } int BFS_B() { int ret = -1; memset(vis_b, false, sizeof(vis_b)); cur_b.step = 0; cur_b.p_pos = cur_p; QB.push(cur_b); while(!QB.empty()) { cur_b = QB.front(); QB.pop(); if(~ret) continue; if(cur_b.x == Gx && cur_b.y == Gy) { ret = cur_b.step; continue; } cur_p = cur_b.p_pos; for(int i = 0; i < 4; i ++) { rear_b.x = cur_b.x + DIR[i][0]; rear_b.y = cur_b.y + DIR[i][1]; rear_b.p_pos.x = cur_b.x - DIR[i][0]; rear_b.p_pos.y = cur_b.y - DIR[i][1]; int &Px = rear_b.p_pos.x; int &Py = rear_b.p_pos.y; if(outRange(rear_b.x, rear_b.y) || outRange(Px, Py)) continue; if(vis_b[rear_b.x][rear_b.y][i]) continue; if(G[rear_b.x][rear_b.y] == 1 || G[Px][Py] == 1) continue; bool suc = BFS_P(Px, Py); if(!suc) continue; rear_b.step = cur_b.step + 1; vis_b[rear_b.x][rear_b.y][i] = true; QB.push(rear_b); } } return ret; } int main() { #ifndef ONLINE_JUDGE FIN; #endif // ONLINE_JUDGE scanf("%d", &T); while(T --) { scanf("%d %d", &N, &M); for(int i = 0; i < N; i++) { for(int j = 0; j < M; j++) { scanf("%d", &G[i][j]); if(G[i][j] == 2) { cur_b.x = i; cur_b.y = j; } else if(G[i][j] == 3) { Gx = i; Gy = j; } else if(G[i][j] == 4) { cur_p.x = i; cur_p.y = j; } } } int res = BFS_B(); printf("%d\n", res); } return 0; }
相关文章推荐
- windows中如何找到端口号对应的进程并kill
- JNI开发流程
- jQuery应用操作之---网页选项卡(tabs)
- 如何设计数据表、解决数据库并发访问瓶颈、数据库事务----阿里巴巴2015校招研发在线
- Git7--远程仓库
- 指数运算&&整除个数
- Activity的生命周期
- 每天一个linux命令(44)--ss命令
- 向量旋转公式推导
- JNI开发流程
- 【IOS学习】iOS——Block中 __block、__weak 、typeof、define等词的小解释
- Java编程操作XML文件(生成方法四:DOM4J)
- HDU-1166-敌兵布阵(线段树 单点更新)
- 在Eclipse上打包并使用Proguard工具混淆jar包
- Git6--删除文件
- 在科大的最后一个半年
- bzoj 3997: [TJOI2015]组合数学
- 深入研究z-index
- Yii2.0 上传图片
- 了解WiFi入门