题意:一款著名的智力游戏:滚木块。输入地图,输出要完成目标最少的步数。
思路:求最少的步数,那么一般就要用BFS,思路很清晰,就是状态保存的时候要注意了,题目数据时500*500的矩阵,木块是3类状态,竖向的、横向的、站立的,因为存储空间的限制,就只能分开保存这三类状态...这类题一定要细心细心在细心.......
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <memory.h>
#include <cmath>
#include <bitset>
#include <queue>
#include <vector>
using namespace std;
const int BORDER = (1<<20)-1;
const int MAXSIZE = 37;
const int MAXN = 1010;
const int INF = 0x4ffffff;
#define CLR(x,y) memset(x,y,sizeof(x))
#define ADD(x) x=((x+1)&BORDER)
#define IN(x) scanf("%d",&x)
#define OUT(x) printf("%d\n",x)
#define MIN(m,v) (m)<(v)?(m):(v)
#define MAX(m,v) (m)>(v)?(m):(v)
#define ABS(x) ((x)>0?(x):-(x))
#define SET_NODE(no,a,b,c,d) {no.state=a,no.x=b,no.y=c,no.val=d;}
int n,m,ex,ey;
int ans;
bool visit[3][MAXN][MAXN];//0:oo 1:horizon 2:vertical
char g[MAXN][MAXN];
int dir[5][4][3]={
{{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
{{-2,0,4},{1,0,4},{0,-2,2},{0,1,2}},
{{-1,0,2},{1,0,2},{0,-1,1},{0,2,1}},
{{0,0,0},{0,0,0},{0,0,0},{0,0,0}},
{{-1,0,1},{2,0,1},{0,-1,4},{0,1,4}}};
typedef struct{
int state;
int x,y;
int val;
}NODE;
NODE start_node;
int init()
{
CLR(visit,0);
CLR(g,0);
ans = 0;
return 0;
}
int input()
{
int i,j,tmp,k;
int pos[2][2];
int tag = 0;
for(i = 0; i < n; ++i)
scanf("%s",g[i]);
for(i = 0; i < n; ++i)
for(j = 0; j < m; ++j)
{
if(g[i][j] != '#')
{
if(g[i][j] == 'X')
{
pos[tag][0] = i;
pos[tag][1] = j;
++tag;
}
else if(g[i][j] == 'O')
{
g[i][j] = '.';
ex = i;
ey = j;
}
}
}
if(tag == 1)
{
SET_NODE(start_node,1,pos[0][0],pos[0][1],0);
visit[0][start_node.x][start_node.y] = true;
return 0;
}
if(pos[0][0] == pos[1][0])
{
tmp = MIN(pos[0][1],pos[1][1]);
SET_NODE(start_node,2,pos[0][0],tmp,0);
visit[1][start_node.x][start_node.y] = true;
return 0;
}
if(pos[0][1] == pos[1][1])
{
tmp = MIN(pos[0][0], pos[1][0]);
SET_NODE(start_node,4,tmp,pos[0][1],0);
visit[2][start_node.x][start_node.y] = true;
}
return 0;
}
bool _in(const int& x,const int& y)
{
if(x < 0 || x >= n || y < 0 || y >= m)
return false;
return true;
}
bool _check(const NODE& node)
{
int x,y,a,b;
if(node.x < 0 || node.y < 0)
return false;
if(node.state & 1)
{
if(!visit[0][node.x][node.y] && g[node.x][node.y] == '.')
{
visit[0][node.x][node.y] = true;
return true;
}
else
return false;
}
if(node.state & 2)
{
x = a = node.x;
y = node.y;
b = y + 1;
if(visit[1][x][y])
return false;
if(g[x][y] == '#' || g[a][b] == '#')
return false;
visit[1][x][y] = true;
}else
{
x = node.x;
y = b = node.y;
a = x + 1;
if(visit[2][x][y])
return false;
if(g[x][y] == '#' || g[a][b] == '#')
return false;
visit[2][x][y] = true;
}
return true;
}
int bfs()
{
int a,b,x,y,i,j,tmp;
NODE t_node,node;
queue<NODE> que;
while(!que.empty())
que.pop();
que.push(start_node);
while(!que.empty())
{
node = que.front();
que.pop();
if((node.state & 1) && node.x==ex && node.y==ey)
return node.val;
for(int i = 0; i < 4; ++i)
{
x = node.x + dir[node.state][i][0];
y = node.y + dir[node.state][i][1];
SET_NODE(t_node,dir[node.state][i][2],x,y,node.val+1);
if(_check(t_node))
que.push(t_node);
}
}
return -1;
}
int work()
{
ans = bfs();
if(ans == -1)
printf("Impossible\n");
else
printf("%d\n",ans);
return 0;
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
if(!n && !m)
break;
init();
input();
work();
}
return 0;
}