HDU---1732 Push Box【BFS】

Problem Description
Push Box is a classic puzzle game. This game play in a grid, there are five types of block in it, the player, the box, the hole, empty place, and the wall. In every step, player can move up, down, left, or right, if the target place is empty. Moreover, if a box in the target place, and the next place in that direction is empty, player can move to the target place, and then push the box to the next place. Remember, both of the player and boxes can't move out of the grid, or you may assume that there is a wall suround the whole grid. The objective of this game is to push every box to a hole. Now, your problem is to find the strategy to achieve the goal with shortest steps, supposed there are exactly three boxes.
 

Input
The input consists of several test cases. Each test case start with a line containing two number, n, m(1 < n, m ≤ 8), the rows and the columns of grid. Then n lines follow, each contain exact m characters, representing the type of block in it. (for empty place, X for player, * for box, # for wall, @ for hole). Each case contain exactly one X, three *, and three @. The input end with EOF.
 

Output
You have to print the length of shortest strategy in a single line for each case. (-1 if no such strategy)
 

Sample Input
  
  
4 4 .... ..*@ ..*@ .X*@ 6 6 ...#@. @..*.. #*##.. ..##*# ..X... .@#...
 

Sample Output
  
  
7

11

SOURCE:点击打开链接

题意:

推箱子游戏,永远都是三个箱子,三个洞。问把所有箱子都推进洞所需要的最少步数。‘@’表示洞,‘*’表示箱子,‘.’表示通路,‘X’表示人的初始位置,‘#’表示墙壁。

解析:

广度优先搜索,需要用vis[][][][][][][][]八位数组来表示一种状态,每种状态为3个箱子及一个人位置的坐标

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#define N 9
using namespace std;

int m,n;
int dx[4]= {1,0,-1,0};
int dy[4]= {0,1,0,-1};
char str[N][N];
bool vis[N][N][N][N][N][N][N][N];//3个箱子一个人的位置为一种状态

struct node//用来存储箱子及人的位置
{
    int x[4];
    int y[4];
    int step;
} Begin;

bool judge(const int x,const int y) //判断是否出界或撞墙
{
    if(x>=0&&x<n&&y>=0&&y<m&&str[x][y]!='#')
        return true;
    else
        return false;
}
int bfs();
int main(void)
{
    int t;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        t=0;
        memset(vis,0,sizeof(vis));
        for(int i=0; i<n; i++)
            for(int j=0; j<m; j++)
            {
                cin>>str[i][j];
                if(str[i][j]=='X')
                {
                    Begin.x[3]=i;
                    Begin.y[3]=j;
                }
                else if(str[i][j]=='*')
                {
                    Begin.x[t]=i;
                    Begin.y[t++]=j;
                }
            }
        Begin.step=0;
        cout<<bfs()<<endl;
    }
    return 0;
}

int bfs()
{
    node now,next;
    queue<node> q;
    bool flag;
    q.push(Begin);
    vis[Begin.x[0]][Begin.y[0]][Begin.x[1]][Begin.y[1]][Begin.x[2]][Begin.y[2]][Begin.x[3]][Begin.y[3]] = 1;
    while(q.size())
    {
        now=q.front();
        q.pop();
        if(str[now.x[0]][now.y[0]]=='@'&&str[now.x[1]][now.y[1]]=='@'&&str[now.x[2]][now.y[2]]=='@')
            return now.step;
        for(int i=0; i<4; i++)
        {
            next=now;
            next.x[3]+=dx[i];
            next.y[3]+=dy[i];
            if(judge(next.x[3],next.y[3])==false)//判断人走一步是否出界或撞墙
                continue;
            flag=false;
            for(int j=0; j<3; j++)
            {
                if(next.x[3]==next.x[j]&&next.y[3]==next.y[j]) //判断人是否走到了箱子的位置
                {
                    next.x[j]+=dx[i];//若走到了箱子的位置则向前移动箱子
                    next.y[j]+=dy[i];
                    if(judge(next.x[j],next.y[j])==false) //判断箱子移动后是否出界或撞墙
                    {
                        flag=true;
                        break;
                    }
                }
                for(int k=0; k<3; k++) //判断箱子移动后是否移动到了其他箱子的地方
                    if(k!=j&&next.x[k] == next.x[j] && next.y[k] == next.y[j])
                    {
                        flag=true;
                        break;
                    }
            }
            if(flag) 
                continue;
            if(!vis[next.x[0]][next.y[0]][next.x[1]][next.y[1]][next.x[2]][next.y[2]][next.x[3]][next.y[3]])
            {
                vis[next.x[0]][next.y[0]][next.x[1]][next.y[1]][next.x[2]][next.y[2]][next.x[3]][next.y[3]]=1;
                next.step = now.step+1;
                q.push(next);
            }
        }
    }
    return -1;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值