题意:一款著名的智力游戏:滚木块。输入地图,输出要完成目标最少的步数。
思路:求最少的步数,那么一般就要用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 ;
}