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>
#include<cstdio>
#include<queue>
using namespace std;
int map[9][9],n,m;
bool hash[9][9][9][9];
int dir[4][2]={{0,1},{0,-1},{1,0},{-1,0}};
struct node
{
    int x,y;
};
struct state
{
    node h,box;
    int st;
    bool operator<(const state& p)const
    {
        return st>p.st;
    }

    bool isok()
    {
        if(h.x>=0&&h.x<n&&h.y>=0&&h.y<m&&map[h.x][h.y]!=1) return true;
        return false;
    }

}a,b;

void sethash(state cur)
{
    hash[cur.h.x][cur.h.y][cur.box.x][cur.box.y]=true;
}

bool gethash(state cur)
{
    return hash[cur.h.x][cur.h.y][cur.box.x][cur.box.y];
}

bool find(state cur)
{
    if(map[cur.box.x][cur.box.y]==3) return true;
    return false;
}
bool isbox(state cur)
{
    if(cur.h.x==cur.box.x&&cur.h.y==cur.box.y) return true;
    return false;
}
bool logic(state cur,int d)
{
    state next;
    next.h.x=cur.h.x+dir[d][0];
    next.h.y=cur.h.y+dir[d][1];
    if(!next.isok()) return false;
    return true;
}
int bfs()
{
    priority_queue<state> q;
    a.st=0;
    q.push(a);
    while(!q.empty()){
        a=q.top(),q.pop();
        if(find(a)){
            return a.st;
        }
        for(int i=0;i<4;++i){
            b=a;
            b.h.x=a.h.x+dir[i][0];
            b.h.y=a.h.y+dir[i][1];
            if(!b.isok()) continue;
            if(isbox(b)){
                if(logic(b,i)){
                    b.box.x+=dir[i][0];
                    b.box.y+=dir[i][1];
                    b.st++;
                    if(!gethash(b)){
                        sethash(b);
                        q.push(b);
                    }
                }
            }
            else{
                if(!gethash(b)){
                    sethash(b);
                    q.push(b);
                }
            }
        }
    }
    return -1;
}

int main()
{
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    int t;
    cin>>t;
    while(t--){
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;++i){
            for(int j=0;j<m;++j){
                scanf("%d",&map[i][j]);
                if(map[i][j]==2){
                    a.box.x=i;
                    a.box.y=j;
                }
                if(map[i][j]==4){
                    a.h.x=i;
                    a.h.y=j;
                }
            }
        }
        memset(hash,false,sizeof hash);
        sethash(a);
        printf("%d\n",bfs());
    }

    return 0;
}</span>

BFS+DFS

dfs出人能到达的点,用一个2维数组标记,然后要想能够推箱子,那么人必须站在箱子的后面,那么我们只要判断人能不能到达箱子的后方,箱子的前方是不是空地就OK啦

在bfs中嵌套dfs

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#define M 9
using namespace std;
int map[M][M];
bool  vis[M][M][4];
bool pvst[M][M];
int dir[4][2]={{0,1},{-1,0},{0,-1},{1,0}};//方向为  右上左下
int n,m;
struct node
{

    int x,y,st,hx,hy;
    node(){}
    node(int _x,int _y,int _hx,int _hy,int _st):x(_x),y(_y),hx(_hx),hy(_hy),st(_st){}
};

bool jd(int x,int y)//判断位置是否合法
{
    if(x>=0&&x<n&&y>=0&&y<m&&map[x][y]!=1) return true;
    return false;
}

bool find(node cur)//箱子是不是到洞里去啦
{
    if(map[cur.x][cur.y]==3) return true;
    return false;
}

void dfs(int x,int y,int a,int b)//搜索人能够到达的点
{
    pvst[x][y]=1;
    for(int i=0;i<4;++i){
        int tx=x+dir[i][0];
        int ty=y+dir[i][1];
        if(tx==a&&ty==b) continue;
        if(jd(tx,ty)&&!pvst[tx][ty]) dfs(tx,ty,a,b);
     }
}

int bfs(int x,int y,int px,int py)
{
    queue<node> q;
    node a,b;
    q.push(node(x,y,px,py,0));
    while(!q.empty()){
        a=q.front();q.pop();
        if(find(a)){
            return a.st;
        }
        for(int i=0;i<4;++i){
            memset(pvst,false,sizeof pvst);
            dfs(a.hx,a.hy,a.x,a.y);  //搜索人能到达的位置
            b=a;
            int pa=a.x+dir[(i+2)%4][0];  //箱子的后方,根据自己定义的方向,i取相应的加减
            int pb=a.y+dir[(i+2)%4][1];
            if(jd(pa,pb)&&pvst[pa][pb]){//人能到箱子的后面
                b.x=a.x+dir[i][0];
                b.y=a.y+dir[i][1];
                if(jd(b.x,b.y)&&!vis[b.x][b.y][i]){//箱子的前面没有墙
                    b.hx=a.x;//吧人的位置变为原来箱子的位置
                    b.hy=a.y;
                    b.st++;//那我就推啦^-^
                    vis[b.x][b.y][i]=1;  //标记状态
                    q.push(b);
                }
            }
        }

    }
    return -1;
}
int main()
{
    freopen("input.txt","r",stdin);

    int t;
    cin>>t;
    while(t--){
        scanf("%d%d",&n,&m);
        int px,py,x,y;
        for(int i=0;i<n;++i){
            for(int j=0;j<m;++j){
                scanf("%d",&map[i][j]);
                if(map[i][j]==4){
                    px=i;
                    py=j;
                }
                if(map[i][j]==2){
                    x=i;
                    y=j;
                }
            }
        }
        memset(vis,false,sizeof vis);
        printf("%d\n",bfs(x,y,px,py));
    }
    return 0;
}<span style="color:#009900;">
</span>

HDU 1254——推箱子

时间: 2024-11-05 12:29:05

HDU 1254——推箱子的相关文章

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 推箱子 (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

poj 1254 推箱子

New~ 欢迎“热爱编程”的高考少年——报考杭州电子科技大学计算机学院 关于2015年杭电ACM暑期集训队的选拔 欢迎参加: 浙江杭电{安控杯}Hackthon 推箱子 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6027    Accepted Submission(s): 1721 Problem Description 推箱子

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

hdu 1254(两个BFS) 推箱子

http://acm.hdu.edu.cn/showproblem.php?pid=1254 首先,要判断人是不是可以从4到达箱子的位置2,而且不止判断一次,因为推动箱子一步后,人的位置也会改变,所以每次移动箱子前都要判断 所以这里要用两个搜索,当每朝着一个方向移动一步箱子的时候,就需要判断 从 此刻的 人位置能不能到达箱子反方向的那个位置(人只能推箱子, 不能拉什么的)  注意人在移动的时候箱子对于人来说也算障碍物,这里需要开一个hash1的四维数组记录走过的位置,不然会死循环超时间 这个记录

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

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

HDU 1254

http://acm.hdu.edu.cn/showproblem.php?pid=1254 暴搜,状态是四维的(箱子和人的坐标),向一个方向推箱子还要判断人能否走到推的位置,1A #include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; int n, m; int tx, ty; int vis[8][8][8][8],vis