hdu 1254(推箱子游戏bfs+状态标记)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1254

推箱子

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 5181    Accepted Submission(s): 1439

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

1
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

Sample Output

4

题意:      如题就是推箱子,熟悉推箱子的规则即可;

思路:(1)这道题初看不好弄,后来学到了一种状态标记的方法,用一个数组vis[][][][]标记当前的状态,(状态包括当前人的位置,当前箱子的位置,当前的推箱子的步数)

(2)因为在每一步的过程中可能会出现之前出现过的状态,所以得标记一下防止同样状态的节点入队;

(3)优先队列优化~

(4)细心才能AC~

#include <iostream>
#include <stdio.h>
#include <string>
#include <string.h>
#include <queue>
using namespace std;
int map[10][10];
int n,m,px,py,sx,sy,ex,ey;//设置全局变量,分别是人的初始位置,箱子的初始位置,箱子的终点位置
bool vis[10][10][10][10];//标志状态

int xx[]={0,0,-1,1};//设置方向数组优化广搜
int yy[]={-1,1,0,0};

struct node
{
 int px,py;//人的位置
 int sx,sy;
 int step;
 bool operator <(const node &p) const
 {
   return p.step<step;
 }
};

void bfs(int x,int y)
{
  memset(vis,false,sizeof(vis));
  priority_queue<node>que;
  node q,p;
  q.px=x;q.py=y;q.sx=sx;q.sy=sy;q.step=0;
  vis[q.px][q.py][q.sx][q.sy]=true;
  que.push(q);
  while(!que.empty())
  {
   q=que.top();
   que.pop();
   if(q.sx==ex&&q.sy==ey)
   {
      printf("%d\n",q.step);
      return;
   }
   for(int i=0;i<4;i++)
   {
       p.px=q.px+xx[i];
       p.py=q.py+yy[i];
       p.sx=q.sx;
       p.sy=q.sy;
       p.step=q.step;
       //判可行性
       if(p.px<1||p.px>n||p.py<1||p.py>m) continue;
       if(map[p.px][p.py]==1||vis[p.px][p.py][p.sx][p.sy]) continue;
       if(p.px==p.sx&&p.py==p.sy)//找到箱子,那么就沿着前进这个方向推
       {
           p.sx=p.sx+xx[i];
           p.sy=p.sy+yy[i];
           p.step+=1;
           //判可行性
           if(p.sx<1||p.sx>n||p.sy<1||p.sy>m)continue;
           if(map[p.sx][p.sy]==1||vis[p.px][p.py][p.sx][p.sy])continue;
       }
       que.push(p);
       vis[p.px][p.py][p.sx][p.sy]=true;
   }
  }
  printf("-1\n");
}

int main()
{
        int T;
        cin>>T;
        while(T--)
        {
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)
             for(int j=1;j<=m;j++)
             {
              scanf("%d",&map[i][j]);
              if(map[i][j]==2)
              {
                 sx=i;
                 sy=j;
                 //map[i][j]=0;
              }
              else if(map[i][j]==3)
              {
                 ex=i;
                 ey=j;
                // map[i][j]=0;
              }
              else if(map[i][j]==4)
              {
                 px=i;
                 py=j;
                // map[i][j]=0;
              }
             }
              bfs(px,py);
        }
        return 0;
}
时间: 2024-10-15 09:32:25

hdu 1254(推箱子游戏bfs+状态标记)的相关文章

HDU 1254 推箱子

一个很有意思的 BFS+DFS.附 数据. 本来今天的任务是多重背包,结果为了帮别人找WA点,自己也坑在这道题上了. 最后想了一组自己都没过的数据-发现想法都不对-果断换思路了. 正确思路是以箱子为起点做BFS找最短.每次移动的时候DFS判断人能不能移动到箱子的后面. 开始就我写一个BFS,什么数据都过了.这组过不了 1 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 实际上答案是2. 我写的是总步数最短时,箱子的最短步数.

HDU 1254——推箱子

这题跟 hdu 1734 push box 是一样的,只不过这题推的是一个箱子,另外求的是箱子被推了多少次,那么只要在箱子被推的时候 次数才加1,然后使用优先队列就ok了 写了1734就会觉得这题很水啦  HDU1734题解 网上主流的都是bfs+bfs,或者是bfs+dfs <span style="font-size:18px;">#include<iostream> #include<cstring> #include<algorithm

hdu - 1254 推箱子 (bfs+bfs)

http://acm.hdu.edu.cn/showproblem.php?pid=1254 题目意思很简单,只要思路对就好. 首先考虑搬运工能否到达推箱子的那个点,这个可以根据箱子前进方向得出搬运工需要到达的目的地,用另一个bfs判断,然后就类似两个点的bfs那样用一个数组标记状态, 需要注意箱子在边上的情况. 1 #include<cstdio> 2 #include<cstring> 3 #include<queue> 4 using namespace std;

搜索 [HDU 1254] 推箱子

推箱子 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5343    Accepted Submission(s): 1503 Problem Description 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子

HDU 1254 推箱子 BFS

囧,一开始没有管人的情况,只看箱子,果然SB了. #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector> #include <string> #include <queue> #include <deque> #include <bitset

HDU 1254 (经典游戏)推箱子 BFS+dfs

Problem Description 推箱子是一个很经典的游戏.今天我们来玩一个简单版本.在一个M*N的房间里有一个箱子和一个搬运工,搬运工的工作就是把箱子推到指定的位置,注意,搬运工只能推箱子而不能拉箱子,因此如果箱子被推到一个角上(如图2)那么箱子就不能再被移动了,如果箱子被推到一面墙上,那么箱子只能沿着墙移动. 现在给定房间的结构,箱子的位置,搬运工的位置和箱子要被推去的位置,请你计算出搬运工至少要推动箱子多少格. Input 输入数据的第一行是一个整数T(1<=T<=20),代表测试

推箱子游戏

本游戏为推箱子游戏,即通过移动方向键来控制小人去推动箱子,直到把所有的箱子都推动到各个目标中.游戏需要在人物行走过程中无法穿越墙和箱子,并在有限的范围中放好各箱子,且每次只能搬运一个箱子.所基于的语言是8086汇编,使用的编译环境是唐都的集中开发环境TD-PIT. 本次设计的基本思想是通过将不同的元素(墙.路.箱子.人.目标位)抽象为不同的矩阵,然后将所设计的地图描抽象成一个控制矩阵来控制图像的显示,每一个控制矩阵块代表一个元素,我们通过不断刷新控制矩阵来达到显示人物移动及推箱子的效果. 1.1

用C写一个简单的推箱子游戏(一)

我现在在读大二,我们有一门课程叫<操作系统>,课程考查要求我们可以写一段程序或者写Windows.iOS.Mac的发展历程.后面我结合网上的资料参考,就想用自己之前简单学过的C写一关的推箱子小程序. 这一程序主要用到了C语言中的二维数组,头文件#include<conio.h>(因为要调用getch()函数以记录输入内容),switch函数等. 一.     功能概述 a)   游戏规则概述 玩家通过键盘输入W.S.A.D四键或者“↑”.“↓”.“←”.“→”四个方向键推动箱子,而

JavaScript写一个小乌龟推箱子游戏

推箱子游戏是老游戏了, 网上有各种各样的版本, 说下推箱子游戏的简单实现,以及我找到的一些参考视频和实例: 推箱子游戏的在线DEMO : 打开 如下是效果图: 这个拖箱子游戏做了移动端的适配, 我使用了zepto的touch模块, 通过手指滑动屏幕就可以控制乌龟走不同的方向: 因为推箱子这个游戏比较简单, 直接用了过程式的方式写代码, 模块也就是两个View 和 Model, 剩下就是用户的事件Controller, 用户每一次按下键盘的方向键都会改变数据模型的数据,然后重新生成游戏的静态htm