【杭电oj】1254 - 推箱子(dfs+bfs+优先队列)

来源:互联网 发布:如何优化亚马逊关键词 编辑:程序博客网 时间:2024/05/16 08:51

点击打开题目

推箱子

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 7258    Accepted Submission(s): 2079


Problem Description
推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子,因此如果箱子被推到一个角上(如图2)那么箱子就不能再被移动了,如果箱子被推到一面墙上,那么箱子只能沿着墙移动.

现在给定房间的结构,箱子的位置,搬运工的位置和箱子要被推去的位置,请你计算出搬运工至少要推动箱子多少格.


 

Input
输入数据的第一行是一个整数T(1<=T<=20),代表测试数据的数量.然后是T组测试数据,每组测试数据的第一行是两个正整数M,N(2<=M,N<=7),代表房间的大小,然后是一个M行N列的矩阵,代表房间的布局,其中0代表空的地板,1代表墙,2代表箱子的起始位置,3代表箱子要被推去的位置,4代表搬运工的起始位置.
 

Output
对于每组测试数据,输出搬运工最少需要推动箱子多少格才能帮箱子推到指定位置,如果不能推到指定位置则输出-1.
 

Sample Input
15 50 3 0 0 01 0 1 4 00 0 1 0 01 0 2 0 00 0 0 0 0
 

Sample Output
4
 

Author
Ignatius.L & weigang Lee



跟UVALive的题一模一样,给一个传送门,注意两道题的w和h的顺序不同。

传送门:点击打开链接


代码如下:

#include <cstdio>#include <cstring>#include <queue>#include <algorithm>using namespace std;int w,h;int endd_x,endd_y;int move_x[] = {0,0,1,-1};int move_y[] = {1,-1,0,0};bool used[10][10][5];//记录箱子从四个方向移动到x,y点:1上,2下,3左,4右int map[10][10];bool mark[10][10];//人物的移动(dfs) bool go;//人物是否能移动到推箱子的位置 int ach_x,ach_y;//人物的目标点 struct node{int x,y,step;int px,py;//推箱子人的位置bool friend operator < (node a , node b){return a.step > b.step;}}pr,ne;//以上是所有变量bool check_ach(node a)//是否完成目标 {if (a.x == endd_x && a.y == endd_y)return true;return false;}void dfs(int x,int y){if (go)return;if (x < 1 || x > h || y < 1 || y > w || mark[x][y])return;if (x == ach_x && y == ach_y){go = true;return;}mark[x][y] = true;for (int i = 0 ; i < 4 ; i++)dfs(x + move_x[i] , y + move_y[i]);}bool check_move(node a,int op)//检查能否移动(注意检查的点是未移动的点,第二个参数是移动方向) {int gx,gy,px,py;//箱子要到达的位置,推箱子人要站到的位置gx = a.x + move_x[op];gy = a.y + move_y[op];if (gx < 1 || gx > h || gy < 1 || gy > w || map[gx][gy] == 1 || used[gx][gy][op])return false;//不能移动//再检查推箱子人是否能移动px = a.x - move_x[op];py = a.y - move_y[op];if (px < 1 || px > h || py < 1 || py > w || map[px][py] == 1)//初步检查 return false;//dfs检查 memset (mark,false,sizeof (mark));//true为不能移动的位置 for (int i = 1 ; i <= h ; i++)for (int j = 1 ; j <= w ; j++)if (map[i][j] == 1)mark[i][j] = true;mark[a.x][a.y] = true;go = false;ach_x = px;ach_y = py;dfs(a.px,a.py);if (go)//如果也可以移动到对应推箱子的位置,则可以推 return true;return false;}int bfs(){memset (used,false,sizeof (used));priority_queue<node> Q;pr.step = 0;Q.push(pr);while (!Q.empty()){pr = Q.top();Q.pop();if (check_ach(pr))//先检查是否完成了目标 return pr.step;for (int i = 0 ; i < 4 ; i++)//否则考虑往四个方向移动{if (check_move(pr,i))//检查能否移动{ne.x = pr.x + move_x[i];ne.y = pr.y + move_y[i];ne.px = pr.x;ne.py = pr.y;ne.step = pr.step + 1;used[ne.x][ne.y][i] = true;//能了标记这样移动过Q.push(ne);}}}return -1;}int main(){int u;int ans;scanf ("%d",&u);while (u--){scanf ("%d %d",&h,&w);for (int i = 1 ; i <= h ; i++){for (int j = 1 ; j <= w ; j++){scanf ("%d",&map[i][j]);if (map[i][j] == 3){endd_x = i;endd_y = j;}else if (map[i][j] == 4){pr.px = i;pr.py = j;}else if (map[i][j] == 2){pr.x = i;pr.y = j;}}}ans = bfs();if (ans == -1)printf ("-1\n");elseprintf ("%d\n",ans);}return 0;}


0 0
原创粉丝点击