《ybtoj高效进阶》第一部分第五章例题3 立体推箱子

题目大意

你的任务是操作一个 1 *1 *2 的长方体。
把它从x挪到o,每一次操作4个方向,沿棱滚90°,有#地不能走,E地不能立着,x可能有2个即开始时可以为横着或竖着,但o只有一个,多组数据,给出棋盘大小和棋盘.

思路

如果是立着的,以0表示状态,x,y为坐标,横着的,以1表示,x,y为左边的坐标,竖着的,以2表示,x,y为上面坐标,bfs(某度优先搜索)完成。
code:

#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
char a[502][502];
bool q[502][502][3];
int n,m,q2[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
struct f{
 int x,y,f,s;
} o,o2,o3;
queue<f> p,p2;
void y()
{
 memset(q,0,sizeof(q));
 for (int i=1;i<=n;i++)
 {
  for (int j=1;j<=m;j++)
  {
   if (a[i][j]=='X')
   {
    o.x=i,o.y=j,o.f=0;
    if (a[i+1][j]=='X') o.f=1;
    if (a[i][j+1]=='X') o.f=2;
    o.s=0;
    q[i][j][o.f]=1;
    p.push(o);
    return;
   }
  }
 }
}
void bfs()
{
 while (p.size())
 {
  o=p.front();
  p.pop();
  for (int i=0;i<4;i++)
  {
   int dx=o.x+q2[i][0],dy=o.y+q2[i][1],df;
   if (o.f==1&&i==1) dx++;
   if (o.f==2&&i==3) dy++;
   if (o.f==0)
   {
    if (i==0) dx--;
    if (i==2) dy--;
   }
   if (o.f==1)
   {
    df=1;
    if (i<2) df=0;
   }
   if (o.f==2)
   {
    df=2;
    if (i>1) df=0;
   }
   if (o.f==0)
   {
    df=1;
    if (i>1) df=2;
   }
   if (dx<1||dy<1||dx>n||dy>m) continue;
   if (df==0&&a[dx][dy]=='O')
   {
    cout<<o.s+1<<endl;
    return;
   }
   if (q[dx][dy][df]==1) continue;
   if (a[dx][dy]=='#') continue;
   if (df==1&&a[dx+1][dy]=='#') continue;
   if (df==2&&a[dx][dy+1]=='#') continue;
   if (df==0&&a[dx][dy]=='E') continue;
   o2.x=dx,o2.y=dy,o2.f=df,o2.s=o.s+1;
   p.push(o2);
   q[dx][dy][df]=1;
  }
 }
 cout<<"Impossible"<<endl;
 return;
}
int main()
{
 cin>>n>>m;
 while (n!=0||m!=0)
 {
  p=p2;
  for (int i=1;i<=n;i++)
  {
   for (int j=1;j<=m;j++)
   {
    cin>>a[i][j];
   }
  }
  y();
  bfs();
  cin>>n>>m;
 }
 return 0;
}
上一篇:Python—入门例程(持续更新)


下一篇:罗技502鼠标连点修复