Bloxorz I POJ - 3322 (bfs)

Little Tom loves playing games. One day he downloads a little computer game called 'Bloxorz' which makes him excited. It's a game about rolling a box to a specific position on a special plane. Precisely, the plane, which is composed of several unit cells, is a rectangle shaped area. And the box, consisting of two perfectly aligned unit cube, may either lies down and occupies two neighbouring cells or stands up and occupies one single cell. One may move the box by picking one of the four edges of the box on the ground and rolling the box 90 degrees around that edge, which is counted as one move. There are three kinds of cells, rigid cells, easily broken cells and empty cells. A rigid cell can support full weight of the box, so it can be either one of the two cells that the box lies on or the cell that the box fully stands on. A easily broken cells can only support half the weight of the box, so it cannot be the only cell that the box stands on. An empty cell cannot support anything, so there cannot be any part of the box on that cell. The target of the game is to roll the box standing onto the only target cell on the plane with minimum moves.


The box stands on a single cell

The box lies on two neighbouring cells, horizontally

The box lies on two neighbouring cells, vertically

After Little Tom passes several stages of the game, he finds it much harder than he expected. So he turns to your help.

Input

Input contains multiple test cases. Each test case is one single stage of the game. It starts with two integers R and C(3 ≤ R, C ≤ 500) which stands for number of rows and columns of the plane. That follows the plane, which contains R lines and C characters for each line, with 'O' (Oh) for target cell, 'X' for initial position of the box, '.' for a rigid cell, '#' for a empty cell and 'E' for a easily broken cell. A test cases starts with two zeros ends the input.

It guarantees that

  • There's only one 'O' in a plane.
  • There's either one 'X' or neighbouring two 'X's in a plane.
  • The first(and last) row(and column) must be '#'(empty cell).
  • Cells covered by 'O' and 'X' are all rigid cells.

Output

For each test cases output one line with the minimum number of moves or "Impossible" (without quote) when there's no way to achieve the target cell.  

Sample Input

7 7
#######
#..X###
#..##O#
#....E#
#....E#
#.....#
#######
0 0

Sample Output

10

题意:一个1*1*2的长方体木块,进行滚动,当1*1的一面着地时,称其为‘立’。那么给你一张地图,#代表不能触碰,.代表空地,X代表木块接触的地方(可能有两个),O代表终点,E代表易碎点(木块不能立在上面),求出从起点到终点的最短距离
思路:既然是最短距离,我们很容易想到bfs
那么我们就需要先确定木块状态,我们用0表示木块立着,1表示木块横躺,2表示木块竖躺。
那么用一个结构体三元组(x,y,kind),记录当前状态,横躺时x、y记录y较小的方块,竖躺时x、y记录x较小的方块
另外,我们用next_x【kind】【4】,表示不同状态向四个方向滚动时,x坐标的变化,next_y也一样。
next_kind【kind】【4】表示不同状态下,向各个方向滚动时,状态的变化。

预处理X的时候,我看到另一种处理方法,就是先将地图信息存入数组,然后扫描到第一个X的时候,判断它上下左右是否有X,有就要把这两个X变成.,然后判断原来的位置是否时X(若有则变成了.),是的话kind = 0,不是就判断第二个X在哪个位置

#include<iostream>
#include<cstdio>
#include<string.h>
#include<queue>
using namespace std;

int next_x[3][4] = {-2,1,0,0,-1,1,0,0,-1, 2,0,0};
int next_y[3][4] = {0,0,-2,1,0,0,-1,2,0,0,-1,1};
int next_kind[3][4] = {2,2,1,1,1,1,0,0,0,0,2,2};
int vis[505][505][3];
int r,c;
char maps[505][505];
struct Node
{
    int x,y;
    int kind;
    Node(int x = 0,int y = 0,int kind = 0):x(x),y(y),kind(kind) {}
};

int bfs(Node st,Node ends)
{
    int flag = 0;
    memset(vis,0,sizeof(vis));
    queue<Node>que;
    while(!que.empty())
        que.pop();
    vis[st.x][st.y][st.kind] = 1;
    que.push(st);
    while(!que.empty())
    {
        Node tmp = que.front();
        que.pop();
        for(int i=0; i<4; i++)
        {
            int xx = tmp.x + next_x[tmp.kind][i];
            int yy = tmp.y + next_y[tmp.kind][i];
            int k_kind = next_kind[tmp.kind][i];
            if(k_kind == 0 && xx <= r && xx >= 1 && yy <= c && yy >= 1 && !vis[xx][yy][k_kind] && maps[xx][yy] == '.')
            {
                vis[xx][yy][k_kind] = vis[tmp.x][tmp.y][tmp.kind] + 1;
                que.push(Node(xx,yy,k_kind));
            }
            else if(k_kind == 1 && xx >= 1 && xx <= r && yy >=1 && yy + 1 <= c && !vis[xx][yy][k_kind] && maps[xx][yy] != '#' && maps[xx][yy+1] != '#')
            {
                vis[xx][yy][k_kind] = vis[tmp.x][tmp.y][tmp.kind] + 1;
                que.push(Node(xx,yy,k_kind));
            }
            else if(k_kind == 2 && xx + 1<= r && xx >= 1 && yy >= 1 && yy <= c && !vis[xx][yy][k_kind] && maps[xx][yy] != '#' && maps[xx+1][yy] != '#')
            {
                vis[xx][yy][k_kind] = vis[tmp.x][tmp.y][tmp.kind] + 1;
                que.push(Node(xx,yy,k_kind));
            }
            if(tmp.x == ends.x && tmp.y == ends.y && tmp.kind == ends.kind)
            {
                return vis[ends.x][ends.y][ends.kind]-1;
            }
        }
    }
    return -1;
}

int main()
{
    while(~scanf("%d%d",&r,&c) && r && c)
    {
        char s[505];
        int start = 0;
        Node st;
        Node ends;
        for(int i=1; i<=r; i++)
        {
            for(int j=1; j<=c; j++)
            {
                scanf(" %c",&maps[i][j]);
                if(!start && maps[i][j] == 'X')
                {
                    st.x = i;
                    st.y = j;
                    st.kind = 0;
                    start++;
                    maps[i][j] = '.';
                }
                else if(maps[i][j] == 'X')
                {
                    if(i == st.x)
                        st.kind = 1;
                    else
                        st.kind = 2;
                    maps[i][j] = '.';
                }
                else if(maps[i][j] == 'O')
                {
                    ends.x = i;
                    ends.y = j;
                    ends.kind = 0;
                    maps[i][j] = '.';
                }
            }
        }
        int flag = bfs(st,ends);
        if(flag == -1)printf("Impossible\n");
        else printf("%d\n",flag);
    }
}
View Code

猜你喜欢

转载自www.cnblogs.com/iwannabe/p/10589545.html