poj3322 Bloxorz I(滚箱子游戏) 状压BFS

题目链接:

POJ3322


游戏链接:

http://www.4399.com/flash/6860_3.htm



题意: 有一个长方体,给出它的起始位置(可能竖着,可能躺着)

问它通过滚动最少多少步能到达终点




解题思路:

BFS   由于每一步可能有竖着和横着两种情况,如果是躺着,不可能记录两个坐标,

我们只需要记录靠左上的节点即可,

然后再用一个state表示当前是竖着还是横着,一个dir表示正躺还是侧躺即可 第二个坐标可以根据这两个值得出来

还有要注意的是:1 破碎的块不能让长方体单独竖着

2 到达终点必须是竖着的



代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cmath>
#define maxn 505
using namespace std;
struct node {
    int x,y;
    int state;       // 0竖 1躺
    int dir;	     // 1正躺  2侧躺
    int step;
} head,t;
int vis[maxn][maxn][2][3];
char map[maxn][maxn];
int v[maxn][maxn];
int n,m,ex,ey;

int ok()
{
    if(t.x<1||t.y<1||t.x>n||t.y>m||vis[t.x][t.y][t.state][t.dir])
        return 0;
    int xx=t.x,yy=t.y,dd=t.dir;
    if(t.state==0) {
        if(v[xx][yy]>=2)
            return 1;
        else
            return 0;
    } else {
        int x1,y1;
        if(dd==1)
            x1=xx+1,y1=yy;
        else
            x1=xx,y1=yy+1;
        if(map[xx][yy]=='#'||map[x1][y1]=='#')
            return 0;
        if(v[xx][yy]+v[x1][y1]>=2)
            return 1;
        else
            return 0;
    }
}

void bfs()
{
    memset(vis,0,sizeof(vis));
    queue<node>q;
    vis[head.x][head.y][head.state][head.dir]=1;
    q.push(head);
    while(!q.empty()) {
        head=q.front();
        q.pop();
//        cout<<head.x<<" "<<head.y<<" "<<head.state<<" "<<head.dir<<" "<<head.step<<endl;
        if(head.state==0&&head.x==ex&&head.y==ey) {
            printf("%d\n",head.step);
            return;
        }
        if(head.state==0) {
            t= {head.x-2,head.y,1,1,head.step+1};
            if(ok()) {
                vis[t.x][t.y][t.state][t.dir]=1;
                q.push(t);
            }
            t= {head.x,head.y-2,1,2,head.step+1};
            if(ok()) {
                vis[t.x][t.y][t.state][t.dir]=1;
                q.push(t);
            }
            t= {head.x,head.y+1,1,2,head.step+1};
            if(ok()) {
                vis[t.x][t.y][t.state][t.dir]=1;
                q.push(t);
            }
            t= {head.x+1,head.y,1,1,head.step+1};
            if(ok()) {
                vis[t.x][t.y][t.state][t.dir]=1;
                q.push(t);
            }
        } else if(head.state==1) {
            if(head.dir==1) {
                t= {head.x-1,head.y,0,0,head.step+1};
                if(ok()) {
                    vis[t.x][t.y][t.state][t.dir]=1;
                    q.push(t);
                }
                t= {head.x+2,head.y,0,0,head.step+1};
                if(ok()) {
                    vis[t.x][t.y][t.state][t.dir]=1;
                    q.push(t);
                }
                t= {head.x,head.y-1,1,1,head.step+1};
                if(ok()) {
                    vis[t.x][t.y][t.state][t.dir]=1;
                    q.push(t);
                }
                t= {head.x,head.y+1,1,1,head.step+1};
                if(ok()) {
                    vis[t.x][t.y][t.state][t.dir]=1;
                    q.push(t);
                }
            } else if(head.dir==2) {
                t= {head.x,head.y-1,0,0,head.step+1};
                if(ok()) {
                    vis[t.x][t.y][t.state][t.dir]=1;
                    q.push(t);
                }
                t= {head.x,head.y+2,0,0,head.step+1};
                if(ok()) {
                    vis[t.x][t.y][t.state][t.dir]=1;
                    q.push(t);
                }
                t= {head.x-1,head.y,1,2,head.step+1};
                if(ok()) {
                    vis[t.x][t.y][t.state][t.dir]=1;
                    q.push(t);
                }
                t= {head.x+1,head.y,1,2,head.step+1};
                if(ok()) {
                    vis[t.x][t.y][t.state][t.dir]=1;
                    q.push(t);
                }
            }
        }
    }
    printf("Impossible\n");
    return;
}
char str[1000];
int main()
{
    char a;
    int ss;
    int pos[3][2];
    while(scanf("%d%d",&n,&m)&&(m+n)) {
        ss=1;
        for(int i=1; i<=n; i++){
            scanf("%s",str+1);
            for(int j=1; j<=m; j++) {
                a=str[j];
                map[i][j]=a;
                if(a=='#')
                    v[i][j]=0;
                else if(a=='E')
                    v[i][j]=1;
                else if(a=='.')
                    v[i][j]=2;
                else if(a=='O')
                    v[i][j]=2,ex=i,ey=j;
                else if(a=='X') {
                    v[i][j]=2;
                    pos[ss][0]=i;
                    pos[ss++][1]=j;
                }
            }
        }
        head.state=0;
        head.step=0;
        head.x=pos[1][0];
        head.y=pos[1][1];
        if(ss==2)
            head.dir=0;
        else if(ss==3) {
            head.state=1;
            if(pos[2][0]-pos[1][0]==1)
                head.dir=1;
            else
                head.dir=2;
        }
        bfs();
    }
    return 0;
}

代码写挫了,因为是在比赛中写出来的,当时还挺高兴的

首先 :躺着开始的两个坐标可以改进

bfs()重复12次同样的话(当时脑袋抽了 - -)

状态只需要三维即可 0竖着,1正躺,2侧躺即可


既然是比赛中写出来的 我也不想改了  保留原本吧

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值