poj 3322 Bloxorz I (bfs)

来源:互联网 发布:淘宝达人公域权限开通 编辑:程序博客网 时间:2024/05/16 02:35

题目链接:poj 3322
然后这个题是有游戏的【有毒慎入】:Bloxorz

Bloxorz I

Time Limit: 2000MS Memory Limit: 65536K

Description
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
1.There’s only one ‘O’ in a plane.
2.There’s either one ‘X’ or neighbouring two ‘X’s in a plane.
3.The first(and last) row(and column) must be ‘#’(empty cell).
4.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

有的列表说这是个基础题,有的列表说这是个中档题,都不知道该拿哪个做标准了……

整体来说思路和经典迷宫题没什么大区别,只是方块有三种状态,即战立,横躺和竖躺,to数组加维即可解决。

代码中:
id == 1 → 站立
id == 2 → 竖躺
id == 3 → 横躺
依据id判断应该用to数组的哪一维。

另一个需要注意的是vis数组的状态标记问题。网上题解不少都是开了三维,最后一维为当前这格方块是否还占有上下左右4格或者仅仅站立在这一格这5种状态。我由于昨天晚上做了一道dfs水题,那道题题面用了1, 2, 4, 8的加和来存放上下左右是否有墙:poj 1164,于是导致我首先想到的是类似的方式来记录,1代表站立,2代表竖躺,4代表横躺,采取累加的方式来确定某一状态是否曾达到过。具体思想请自己看f数组和check函数。

#include <iostream>#include <string>#include <cstdio>#include <algorithm>#include <cstring>#include <ctime>#include <cmath>#include <queue>#include <map>#define LL long long#define M 505#define INF 0x3f3f3f3fusing namespace std;struct node{    int x[2], y[2], id, step;}st, ed, tmp, t;int R, C;int to[3][4][5] = {{{1, 0, 2, 0, 2}, {-2, 0, -1, 0, 2}, {0, 1, 0, 2, 3}, {0, -2, 0, -1, 3}},                   {{2, 0, 1, 0, 1}, {-1, 0, -2, 0, 1}, {0, 1, 0, 1, 2}, {0, -1, 0, -1, 2}},                   {{1, 0, 1, 0, 3}, {-1, 0, -1, 0, 3}, {0, 2, 0, 1, 1}, {0, -1, 0, -2, 1}}};char g[M][M];int vis[M][M], f[8][3] = {{0, 0, 0}, {1, 0, 0}, {0, 1, 0}, {1, 1, 0}, {0, 0, 1}, {1, 0, 1}, {0, 1, 1}, {1, 1, 1}};queue<node> Q;void check(node t)//遍历到的方块的状态是否符合条件,并做入队操作{    if(g[t.x[0]][t.y[0]] != '#')    {        if(t.id == 1 && g[t.x[0]][t.y[0]] != 'E' && !f[vis[t.x[0]][t.y[0]]][0])        {            Q.push(t);            vis[t.x[0]][t.y[0]] += 1;//采取累加方式来记录状态        }        else if(t.id == 2 && g[t.x[1]][t.y[1]] != '#' && !f[vis[t.x[0]][t.y[0]]][1])        {            Q.push(t);            vis[t.x[0]][t.y[0]] += 2;//采取累加方式来记录状态        }        else if(t.id == 3 && g[t.x[1]][t.y[1]] != '#' && !f[vis[t.x[0]][t.y[0]]][2])        {            Q.push(t);            vis[t.x[0]][t.y[0]] += 4;//采取累加方式来记录状态        }    }}int bfs(){    memset(vis, 0, sizeof(vis));    while(!Q.empty())   Q.pop();    Q.push(st);    vis[st.x[0]][st.y[0]] = 1;    if(st.id == 2)        vis[st.x[0]][st.y[0]] = 2;    else if(st.id == 3)        vis[st.x[0]][st.y[0]] = 4;    while(!Q.empty())    {        tmp = Q.front();        if(tmp.id == 1 && tmp.x[0] == ed.x[0] && tmp.y[0] == ed.y[0])            return tmp.step;        Q.pop();        for(int i = 0; i < 4; i++)        {            t.x[0] = tmp.x[0] + to[tmp.id - 1][i][0];            t.y[0] = tmp.y[0] + to[tmp.id - 1][i][1];            t.x[1] = tmp.x[1] + to[tmp.id - 1][i][2];            t.y[1] = tmp.y[1] + to[tmp.id - 1][i][3];            t.step = tmp.step + 1, t.id = to[tmp.id - 1][i][4];            check(t);        }    }    return -1;}int main(){    while(scanf("%d %d", &R, &C) && R + C)    {        st.id = 0;        for(int i = 1; i <= R; i++)        {            scanf("%s", g[i] + 1);            for(int j = 1; j <= C; j++)            {                if(g[i][j] == 'X')                {                    if(st.id == 0)                    {                        st.id++;                        st.x[0] = st.x[1] = i, st.y[0] = st.y[1] = j;                    }                    else                    {                        st.x[1] = i, st.y[1] = j;                        if(st.x[0] != st.x[1])                        {                            sort(st.x, st.x + 2);//为了后面记录状态方便,我使它保持x[0] <= x[1]                            st.id = 2;                        }                        else                        {                            sort(st.y, st.y + 2);//为了后面记录状态方便,我使它保持y[0] <= y[1]                            st.id = 3;                        }                    }                }                else if(g[i][j] == 'O')                    ed.x[0] = i, ed.y[0] = j;            }        }        int ans = bfs();        if(ans == -1)            printf("Impossible\n");        else            printf("%d\n", ans);    }    return 0;}

运行结果:
这里写图片描述

0 0
原创粉丝点击