hdoj 1254 推箱子 【BFS+DFS】

来源:互联网 发布:碧之轨迹优化破解补丁 编辑:程序博客网 时间:2024/06/05 05:09

推箱子

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


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
 



0ms。


思路:7*7,直接暴力枚举所有状态即可。

首先若把箱子从(x, y)推到(x+1, y),则人必须在(x-1, y)位置,同理其它三种情况也是这样。只需记录该状态下箱子的位置(x, y)和人的位置(mx, my),判断(mx, my)能否到达(x-1, y)位置即可。这样写好后,提交就WA了。

仔细推敲后,发现在人三面被堵且只有一面是箱子的情况下(或许还有其他情况),不能单纯标记,这样或许得到的不是最优解(可能箱子回到原来的位置才是最优)。人必须要先把箱子推走才可以进行下一步活动,这样的话在未来的某个状态下箱子或许会回到原来的位置。因此在标记状态时,可累计两次。


AC代码:


#include <cstdio>#include <cstring>#include <cmath>#include <cstdlib>#include <algorithm>#include <queue>#include <stack>#include <map>#include <set>#include <vector>#define INF 0x3f3f3f3f#define eps 1e-8#define MAXN (300+10)#define MAXM (100000)#define Ri(a) scanf("%d", &a)#define Rl(a) scanf("%lld", &a)#define Rf(a) scanf("%lf", &a)#define Rs(a) scanf("%s", a)#define Pi(a) printf("%d\n", (a))#define Pf(a) printf("%.2lf\n", (a))#define Pl(a) printf("%lld\n", (a))#define Ps(a) printf("%s\n", (a))#define W(a) while(a--)#define CLR(a, b) memset(a, (b), sizeof(a))#define MOD 1000000007#define LL long long#define lson o<<1, l, mid#define rson o<<1|1, mid+1, r#define ll o<<1#define rr o<<1|1using namespace std;int n, m;int Map[10][10];bool judge(int x, int y){    return x >= 0 && x < n && y >= 0 && y < m;}int vis[10][10];bool use[10][10];int Move[4][2] = {0,1, 0,-1, 1,0, -1,0};bool DFS(int x, int y, int tx, int ty){    use[x][y] = true;    if(x == tx && y == ty)       return true;    for(int i = 0; i < 4; i++)    {        int xx = x + Move[i][0];        int yy = y + Move[i][1];        if(!judge(xx, yy) || Map[xx][yy] == 1 || use[xx][yy]) continue;        if(DFS(xx, yy, tx, ty)) return true;    }    return false;}struct Node{    int x, y, step;    int mx, my;};int sx, sy, tx, ty;int BFS(int x, int y){    queue<Node> Q; CLR(vis, 0);    Node now, next;    now.x = x; now.y = y; now.step = 0; vis[now.x][now.y] = 1;    now.mx = sx, now.my = sy; Q.push(now);    while(!Q.empty())    {        now = Q.front();        Q.pop();        if(Map[now.x][now.y] == 3)            return now.step;        for(int i = 0; i < 4; i++)        {            next.x = now.x + Move[i][0];//箱子下一步移动位置            next.y = now.y + Move[i][1];            if(!judge(next.x, next.y) || vis[next.x][next.y] > 2 || Map[next.x][next.y] == 1) continue;            int xx, yy;//人的目标位置,到这里才可以把箱子推到(next.x, next.y)            switch(i)            {                case 0: xx = now.x + Move[1][0]; yy = now.y + Move[1][1]; break;                case 1: xx = now.x + Move[0][0]; yy = now.y + Move[0][1]; break;                case 2: xx = now.x + Move[3][0]; yy = now.y + Move[3][1]; break;                case 3: xx = now.x + Move[2][0]; yy = now.y + Move[2][1]; break;            }            if(!judge(xx, yy) || Map[next.x][next.y] == 1) continue;            int t;            t = Map[now.x][now.y];            Map[now.x][now.y] = 1;            CLR(use, false);            if(DFS(now.mx, now.my, xx, yy))//人从上次停留的位置 能否 到达目标位置            {                vis[next.x][next.y]++;                next.step = now.step + 1;                next.mx = now.x;                next.my = now.y;                Q.push(next);            }            Map[now.x][now.y] = t;        }    }    return -1;}int main(){    int t; Ri(t);    W(t)    {        Ri(n); Ri(m);        for(int i = 0; i < n; i++)        {            for(int j = 0; j < m; j++)            {                Ri(Map[i][j]);                if(Map[i][j] == 4)                {                    sx = i;                    sy = j;                }                if(Map[i][j] == 2)                {                    tx = i;                    ty = j;                }            }        }        Pi(BFS(tx, ty));    }    return 0;}



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 CAD画图线性数字不居中怎么办 3d立体画笔堵塞怎么办 龋齿树脂填充老化后怎么办 小孩补过的牙疼怎么办 颜料弄到墙纸上怎么办 4岁的宝宝不爱涂色怎么办 oppo手机截图存不到相册怎么办 做的ih5保存不了怎么办 小偷偷东西发现后逃跑了怎么办? 网上有人传迷信诅咒怎么办 颜料粘在衣服上怎么办 家里有小偷撬锁怎么办 在家有人在撬门怎么办 6个月的宝宝腹泻怎么办 六个月大的宝宝拉肚子怎么办 六个月宝宝着凉拉肚子怎么办 六个月婴儿着凉拉肚子怎么办 怀孕六个月着凉拉肚子怎么办 六个月的婴儿消化不好怎么办 六个月婴儿不好好吃奶怎么办 六个月婴儿消化不好怎么办 六个月婴儿肠胃不好怎么办 受了惊吓后睡眠不好怎么办 宝宝夏季吃饭不爱带围嘴怎么办 3岁宝宝爱看电视怎么办 新生儿晚上哭闹不睡觉怎么办 档案丢了怎么办失业证 三岁宝宝不合群怎么办 阴唇手术半月了疤痕增生怎么办 宝宝小阴唇黏连怎么办 6个月宝宝阴唇粘连怎么办? 高一孩子不爱上学怎么办 3岁宝宝外阴发红怎么办 40爸妈离婚我该怎么办 小儿吃糖卡住了怎么办 额头撞墙上肿了怎么办 宝宝额头撞肿了怎么办 小孩额头撞肿了怎么办 宝宝撞到额头肿了怎么办 小孩子上一年级语文很差了怎么办? 楼下说小孩太吵怎么办