算法竞赛进阶指南,112页, 广搜,坐标变换
题目意思:
4433 小游戏上面的 推木头游戏,http://www.4399.com/flash/13071.htm#search3
本题要点:
1、长方体的状态表示, (x, y, lie) 其中 x, y 表示坐标,lie 表示长方体怎样摆放
lie == 0, 长方体立起来,与地面接触只有 的一面是 1 * 1 的正方形
lie == 1, 长方体横向躺着,左半部分在 位置 (x, y)
lie == 2, 长方体竖向向躺着,左半部分在 位置 (x, y)
2、 状态的起点和终点
起点:长方体可能立起来(图形只有1个 ‘X’),可能横躺(图形只有2个 ‘X’), 可能竖躺着(图形只有2个 ‘X’)
终点:长方体只能立起来(图形只有1个 ‘X’)
3、关键的左边变换
next_x[i][j] 表示 lie = i 时朝方向j 滚动后x的变化情况
next_x[i][j] 表示 lie = i 时朝方向j 滚动后y的变化情况
next_x[i][j] 表示 lie = i 时朝方向j 滚动后lie的变化情况
4、 每一种状态 State, 进行有效性判断
#include
#include
#include
#include
using namespace std;
const int MaxN = 510;
struct State
{
int x, y, lie;
};
queue<State> q;
State st, ed; // 起点,终点状态
int n, m;
char s[MaxN][MaxN];
int dist[MaxN][MaxN][3];
const int dx[4] = {
0, 0, -1, 1}, dy[4] = {
-1, 1, 0, 0};//左右上下
const int next_x[3][4] = {
{
0, 0, -2, 1}, {
0, 0, -1, 1}, {
0, 0, -1, 2}};//next_x[i][j] 表示 lie = i 时朝方向j 滚动后x的变化情况
const int next_y[3][4] = {
{
-2, 1, 0, 0}, {
-1, 2, 0, 0}, {
-1, 1, 0, 0}};//next_x[i][j] 表示 lie = i 时朝方向j 滚动后y的变化情况
const int next_lie[3][4] = {
{
1, 1, 2, 2}, {
0, 0, 1, 1}, {
2, 2, 0, 0}};//next_x[i][j] 表示 lie = i 时朝方向j 滚动后lie的变化情况
bool judge_xy(int x, int y)
{
return x >= 1 && x <= n && y >= 1 && y <= m;
}
bool judge(State next) //注意有易碎地面
{
if(!judge_xy(next.x, next.y))
return false;
if(s[next.x][next.y] == '#')
return false;
if(next.lie == 0 && s[next.x][next.y] != '.')
return false;
if(next.lie == 1 && s[next.x][next.y + 1] == '#')
return false;
if(next.lie == 2 && s[next.x + 1][next.y] == '#')
return false;
return true;
}
void parse_st_ed() //处理起点和终点
{
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
{
if('O' == s[i][j]) //终点
{
ed.x = i, ed.y = j, ed.lie = 0;
s[i][j] = '.';
}else if('X' == s[i][j]){
//起点, 这里的 'X' 是第一个
int a, b, lie = 0;
for(int k = 0; k < 4; ++k)
{
a = i + dx[k], b = j + dy[k];
if(a >= 1 && a <= n && b >= 1 && b <= m && 'X' == s[a][b])//这里的 'X' 是第二个
{
if(k == 1)
{
lie = 1;
}else if(k == 3){
lie = 2;
}
s[a][b] = '.';
}
}
st.x = i, st.y = j, st.lie = lie, s[i][j] = '.';
}
}
}
int bfs()
{
while(q.size())
{
q.pop();
}
memset(dist, -1, sizeof(dist));
State s, next;
q.push(st);
dist[st.x][st.y][st.lie] =0;
while(q.size())
{
s = q.front();
q.pop();
for(int j = 0; j < 4; ++j)
{
int i = s.lie;
next.x = next_x[i][j] + s.x;
next.y = next_y[i][j] + s.y;
next.lie = next_lie[i][j];
if(judge(next) && -1 == dist[next.x][next.y][next.lie])
{
dist[next.x][next.y][next.lie] = dist[s.x][s.y][s.lie] + 1;
q.push(next);
if(next.x == ed.x && next.y == ed.y && next.lie == ed.lie)
{
return dist[next.x][next.y][next.lie];
}
}
}
}
return -1;
}
int main()
{
while(scanf("%d%d", &n, &m) != EOF && n)
{
for(int i = 1; i <= n; ++i)
{
scanf("%s", s[i] + 1);
}
parse_st_ed();
int ans = bfs();
if(-1 == ans)
{
printf("Impossible\n");
}else{
printf("%d\n", ans);
}
}
return 0;
}
/*
7 7
#######
#..X###
#..##O#
#....E#
#....E#
#.....#
#######
0 0
*/
/*
10
*/