poj1475 推箱子

本文介绍了一种解决经典推箱子游戏问题的算法实现。通过使用优先队列进行广度优先搜索(BFS),确保找到从初始状态到达目标状态的最短路径。文中详细解释了如何避免重复状态以及如何有效记录移动路径。

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

题意:

将箱子推到目标位置,要求推箱子的次数最少

思路:

1.纯bfs
2.优先队列
3.A*

优先队列

注意记录路径用字符数组(实测1094MS)不用字符串(实测超时)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <cmath>
#include <queue>
using namespace std;

const int M=25;
bool f[M][M];
bool b[M][M][M][M];
char a[M];
int d[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
char dd[4][2]={{'n','N'},{'s','S'},{'w','W'},{'e','E'}};
struct f1
{
  int x,y,sx,sy;
  char c[801]; 
  int t,tt;
  bool operator <(const f1 &q) const
  {
    return (t>q.t)||(t==q.t&&tt>q.tt);
  }
}p,tmp;
int i,j,k,n,m,tot,xx,yy;


bool  FF(int x,int y)
{
  if(x>=1&&x<=n&&y>=1&&y<=m) return true;
  return false;
}

void bfs()
{
  priority_queue <f1> q;
  b[p.x][p.y][p.sx][p.sy]=1;
  p.c[0]='\0';
  p.t=0,p.tt=0;
  q.push(p);
  while(!q.empty())
  {
    p=q.top();
    q.pop();
    //cout<<p.c<<endl;
    for(i=0;i<=3;i++)
    {
      tmp.x=p.x+d[i][0];
      tmp.y=p.y+d[i][1];
        if(tmp.x==p.sx&&tmp.y==p.sy)
        {
          tmp.sx=p.sx+d[i][0];
          tmp.sy=p.sy+d[i][1];
          if(FF(tmp.sx,tmp.sy)&&f[tmp.sx][tmp.sy]&&!b[tmp.x][tmp.y][tmp.sx][tmp.sy])
          {
            b[tmp.x][tmp.y][tmp.sx][tmp.sy]=1;
            for(int k=0;k<p.tt;k++)
              tmp.c[k]=p.c[k];
            tmp.c[p.tt]=dd[i][1];
            tmp.t=p.t+1;
            tmp.tt=p.tt+1;
            q.push(tmp);
            if(tmp.sx==xx&&tmp.sy==yy)
            {
              tmp.c[tmp.tt]='\0';
              printf("%s\n\n",tmp.c); 
              return;
            }
          }
        }
      else if(FF(tmp.x,tmp.y)&&f[tmp.x][tmp.y])
      {
        //cout<<x<<' '<<y<<endl;
        tmp.sx=p.sx;
        tmp.sy=p.sy;
        if(!b[tmp.x][tmp.y][p.sx][p.sy]) 
        {
          b[tmp.x][tmp.y][p.sx][p.sy]=1;
          for(int k=0;k<p.tt;k++)
            tmp.c[k]=p.c[k];
          tmp.c[p.tt]=dd[i][0];
          tmp.t=p.t;
          tmp.tt=p.tt+1;
          q.push(tmp);
        }
      }
    }
  }
  printf("Impossible.\n\n");
}

int main()
{
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  while(~scanf("%d %d",&n,&m))
  {
    if(m+n==0) break;
    tot++;
    printf("Maze #%d\n",tot);
    for(i=1;i<=n;i++)
      for(j=1;j<=m;j++)
      {
        f[i][j]=1;
        for(int k=1;k<=n;k++)
          for(int o=1;o<=m;o++)
            b[i][j][k][o]=0;
      }
    gets(a);
    for(i=1;i<=n;i++)
    {
      gets(a);
      for(j=0;j<m;j++)
      {
        if(a[j]=='#') f[i][j+1]=0;
        else if(a[j]=='T') { xx=i; yy=j+1; }
        else if(a[j]=='S') { p.x=i; p.y=j+1; }
        else if(a[j]=='B') { p.sx=i; p.sy=j+1; }
      }
    }
    bfs();
  }
  fclose(stdin);
  fclose(stdout);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值