hdu 1254(搜索题)

推箱子

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

Problem Description


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

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

Input


入数据的第一行是一个整数T(1<=T<=20),代表测试数据的数量.然后是T组测试数据,每组测试数据的第一行是两个正整数M,N(2&
lt;=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

Author

好多坑的一道题。。。很好的一道题。。。参考了别人的代码。。真的做不出来。。。每次结点存个新的图。。get。。。做了才知道。。。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
int n,m;
int graph[8][8];
bool flag[8][8][4];
bool vis[8][8];
int dir[][2] = {{1,0},{-1,0},{0,1},{0,-1}};
struct Node
{
    int x,y;
    int step;
    int g[10][10];
}s,person,t;
bool check(int x,int y)
{
    if(x<0||x>=n||y<0||y>=m) return false;
    return true;
}
bool bfs2(Node s,Node target){
    person = s;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            if(person.g[i][j]==4){
                person.x = i;
                person.y = j;
                person.step = 0;
            }
        }
    }
    queue<Node>q;
    memset(vis,false,sizeof(vis));
    q.push(person);
    vis[person.x][person.y] = true;
    while(!q.empty()){
        Node now = q.front();
        q.pop();
        if(now.x==target.x&&now.y==target.y){
            return true;
        }
        Node next;
        for(int i=0;i<4;i++){
            next.step = now.step+1;
            next.x = now.x +dir[i][0];
            next.y = now.y + dir[i][1];
            if(!check(next.x,next.y)||s.g[next.x][next.y]==2||vis[next.x][next.y]||s.g[next.x][next.y]==1) continue;
            vis[next.x][next.y] = true;
            q.push(next);
        }
    }
    return false;
}
int bfs(){
    memset(flag,false,sizeof(flag));
    queue <Node> q;
    q.push(s);
    while(!q.empty()){
        Node now = q.front();
        q.pop();
        if(now.x==t.x&&now.y==t.y) return now.step;
        Node next,target;
        for(int i=0;i<4;i++){
            next = now;
            next.x = now.x+dir[i][0];
            next.y = now.y+dir[i][1];
            next.step = now.step+1;
            if(!check(next.x,next.y)||flag[next.x][next.y][i]||next.g[next.x][next.y]==1) continue; ///该方向已经走过了
            ///人的目标点(人以此点为目标点将箱子从now推向next)
            target.x = now.x - dir[i][0];
            target.y = now.y - dir[i][1];
            if(!check(target.x,target.y)) continue;
            if(bfs2(next,target)){
                swap(next.g[now.x][now.y],next.g[next.x][next.y]);
                swap(next.g[target.x][target.y],next.g[person.x][person.y]);
                flag[next.x][next.y][i] = true;
                q.push(next);
            }
        }
    }
    return -1;
}
int main()
{
    int tcase;
    scanf("%d",&tcase);
    while(tcase--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++){
                scanf("%d",&s.g[i][j]);
                if(s.g[i][j]==2){
                    s.x = i;
                    s.y = j;
                    s.step = 0;
                }
                if(s.g[i][j]==3){
                    t.x = i;
                    t.y = j;
                }
            }
       int res = bfs();
       printf("%d\n",res);
    }
}
时间: 2024-10-26 10:01:24

hdu 1254(搜索题)的相关文章

hdu&amp;&amp;poj搜索题题号

搜索 hdu1067 哈希 hdu1401 双向搜索 hdu1430 哈希 hdu1667 跌搜+启发式函数 hdu1685 启发式搜索 hdu1813 启发式搜索 hdu1885 状态压缩搜索 hdu2918 哈希 hdu2931 dfs+dfs hdu2977 bfs+dfs hdu3004 车马炮 hdu3085 双向bfs hdu3900 哈希 hdu4012 状态压缩搜索 hdu4634 状态压缩搜索 poj1324 状态压缩 poj2044 状态压缩 poj3131 双向搜索 poj

hdu 1547 搜索题

先说下题意: 给你个地图     里面有a-z的颜色泡      为你一个点    若与这个点连着的颜色相同超过3个  则会爆炸     之后没有雨最顶端相连(间接相连也行)的也会爆炸 给你个坐标  问你会爆炸多少个      先深搜(或广搜)找到多少个  会爆炸    大于三个在对第一行的所有点进行广搜找到所有相连的点   用总的减去就行 做了这道题明白一个道理   题目的图不是没用的,,   为此还贡献了几次wa           这道题做起来比较容易  就是得先搞清楚球是交叉排的    

50道hdu基础搜索总结(转)

Dfs: 大部分是直接递归枚举,即求满足约束条件下的解,虽不用剪枝,但也需要代码能力. 练习递归枚举的题目: 1241       Oil Deposits (dfs的连通块个数) 1016       Prime Ring Problem 1584       蜘蛛牌(简单dfs,简单的剪枝,还有人用DP做(???)) 1426       Sudoku Killer(练习递归的好题目 or Dancing links(???)) 2510       符号三角形(打表题,写写打表程序还是不错

搜索题推荐

(转自网络博客): POJ POJ 1376 – Robot(基础) http://acm.pku.edu.cn/JudgeOnline/problem?id=1376 题意:略 解法:bfs,A*-. POJ 2688 – Cleaning Robot(基础) http://acm.pku.edu.cn/JudgeOnline/problem?id=2688 题意:bfs后转换为tsp问题 解法:bfs+dp,bfs+dfs 相关:http://hi.baidu.com/zfy0701/blo

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

ACM 暴力搜索题 题目整理

UVa 129 Krypton Factor 注意输出格式,比较坑爹. 每次要进行处理去掉容易的串,统计困难串的个数. #include<iostream> #include<vector> #include<cmath> #include<map> #include<algorithm> #include<cstring> #include<cstdio> #include<cstdlib> #include

经典搜索题

今天搞了一下传说中的经典搜索题——poj1011,果然里面充斥着各种巧妙的剪枝,做完之后回味一下还是感觉构思太巧妙,所以总结记录一下加深理解. 原题:http://poj.org/problem?id=1011 刚开始接触搜索的初学者面对这道题可能感觉无从下手,即便是告诉了要用深搜解决这道题,也不知道怎么用,我现在也对搜索有了更多的理解与体会,其实不要把搜索只理解为在一个地图上找点,其实搜索更可以抽象为当面对多个选择的时候如何抉择,深搜就是先认准一个方向走下去,不行再回来,走别的路:广搜就是把每

关于10月12日#2的四道搜索题的心得与感悟

今天上午开始写姜神的搜索题. 第一道,经典八数码,重新复习康托展开与BFS.代码写得太弱,外加对题理解不充分,调了一上午的码. 第二题,八数码变种,数据更水,把握住翻转的扩展规律即可. 第三题,还在施工 第四题,一开始DFS暴力,TLE掉;后来开始用DFS记忆化搜索,失败;接着尝试BFS+DP,TLE掉.最后在网上看了题解,利用DP解决. 在DP的过程中要留意边界.另外状态转移的时候很容易写出模模糊糊的错误转移.在这题中,先处理好一排或一列,在逐层或逐列转移,可以避免重复计算导致的超时. 第四题

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. 我写的是总步数最短时,箱子的最短步数.