XUM 1457 推箱子 状态搜索

本文详细介绍了经典游戏“推箱子”的算法实现过程,包括状态搜索和状态记录等关键步骤,并提供了一个具体的示例来说明如何求解最少移动步数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1457.推箱子
Time Limit: 3000 MS           Memory Limit: 65536 K  
Total Submissions: 82 (18 users)           Accepted: 28 (14 users)  
[ My Solution ]

Description

推箱子是个家喻户晓的游戏相信在大家小的时候都一定玩过。当然我们在这里还是做个简单介绍如下图所示游戏玩家初始站在地图的某个位置游戏目标是将图中的箱子全部移往目的地(下图X的位置), 每次移动只能选择上下左右方向上某个方向移动一格若移动的方向上有箱子存在则箱子也往相同的方向移动一格并且在移动过程中玩家(和箱子)不能穿越(或停留于)箱子、障碍物(下图树的位置)和边界区域的位置。除此之外为了尽可能的得到最高分玩家还应该以尽可能少的步数完成任务。

 

为了简化问题现在给你一个地图,  且地图上的游戏者、箱子和目的地都各只有一个你需要求出最少需要多少步才能完成任务呢?

Input

输入的第一行有2个整数n, m (2 <= n, m <= 30), 接下来有n行, 每行有m个只由'.' , '*' , 'P', 'B', 'E' 构成的字符, 其中, ‘.’表示可通行区域, '*' 表示障碍物, 'P'表示玩家, 'B'表示箱子, 'E'表示目的地, 输入保证字符'P', 'B', 'E'各只有一个。

Output

若无法完成任务, 则输出-1, 否则输出的第一行有一个数字n, 表示将箱子移至目的地的最少步数, 第二行有n个字符, 表示玩家的移动步骤, 其中'L'表示左移, 'R'表示右移, 'U'表示上移, 'D'表示下移。(若存在多种满足题意的方案, 则任意一组答案都可以通过本题)

Sample Input

6 7
...*...
.*.*.*.
.*...*.
.*.**..
.****B*
.....EP

Sample Output

26
LLLLLLUUUUURRDDRRUURRDDDLD

Hint

这是一道SPECIAL JUDGE的题目, 每组数据, 时限1s

 

/*

这道题不难的,搞了我两天了。状态搜索,采用状态记录的方法,就可以过了 

*/
#include<iostream>    
#include<string>    
#include<cstdio>    
#include<queue>    
#include<algorithm>    
#define manx 30*30*30*31  
using namespace std;    
    
struct node{    
    int x,y;    
    int bx,by;    
    int temp;    
    int num; ////前一个状态地址 
}que[manx];    
    
int sx,sy,bx,by,ex,ey,n,m,a,b;    
bool s[31][31][31][31]; ////所有状态     
char mp[31][31];    
  
void init(){    
    a=0; b=-1;  
    for(int i=1;i<=n;++i){    
        for(int j=1;j<=m;++j){    
            if(mp[i][j]=='*') continue;    
            for(int r=1;r<=n;++r){    
                for(int k=1;k<=m;++k)    
                    s[i][j][r][k]=0;    
            }    
        }    
    }    
}    
    
void judge(int x,int y,int bx,int by,char str,int temp){    
    if(x<1||x>n || y<1||y>m || mp[x][y]=='*') return;    
    if(x==bx && y==by){    
        if(str=='U') bx--;    
        if(str=='D') bx++;    
        if(str=='L') by--;    
        if(str=='R') by++;    
        if(bx<1||bx>n || by<1||by>m || mp[bx][by]=='*') return;    
    }    
    if(s[x][y][bx][by]) return;    
    s[x][y][bx][by]=1;    
    node te;    
    te.x=x; te.y=y;    
    te.bx=bx; te.by=by; 
    te.temp=temp;    
    te.num =a-1;////连接 
    que[++b]=te;    
}    

void PN (node te){
    string str;
    while(te.num>=0){
        node p = que[te.num];
        if(p.x==te.x){
            if(p.y-te.y>0) str+='L'; ///left
            else  str+='R'; ///right
        }
        if(p.y==te.y){
            if(p.x>te.x) str+='U'; ///up
            else str+='D'; /// down 
        }
        te = p;
    }
    for(int i=str.size()-1; i>=0; i--)
        cout<<str[i];
    cout<<endl;
}
    
void bfs(){    
    node te;    
    te.x=sx; te.y=sy;    
    te.bx=bx; te.by=by;    
    te.temp=0;    
    te.num = -1;
    que[++b]=te;     
  //  cout<<a<<" "<<b<<endl;   
    while(a<=b){    
        te=que[a];    
        ++a;     
        if(te.bx==ex && te.by==ey){    
            printf("%d\n",te.temp); 
            PN(te); 
            return ;    
        }    
        judge(te.x+1, te.y, te.bx, te.by, 'D', te.temp+1);//xiang xia    
        judge(te.x-1, te.y, te.bx, te.by, 'U', te.temp+1);//xiang shang    
        judge(te.x, te.y+1, te.bx, te.by, 'R', te.temp+1);//xiang you    
        judge(te.x, te.y-1, te.bx, te.by, 'L', te.temp+1);//xiang zuo    
    }    
    printf("-1\n");    
}    
    
int main(){    
    while(scanf("%d%d",&n,&m)!=EOF){    
        for(int i=1;i<=n;++i){    
            scanf("%s",mp[i]+1);  
            for(int j=1;j<=m;++j){    
                if(mp[i][j]=='B'){ bx=i,by=j; }    
                if(mp[i][j]=='E'){ ex=i,ey=j; }    
                if(mp[i][j]=='P'){ sx=i,sy=j; }    
            }    
        }    
        init();    
        s[sx][sy][bx][by]=1;    
        bfs();    
    }    
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值