POJ 1324 [Holedox Moving] 状态压缩BFS

题目链接:http://poj.org/problem?id=1324

题目大意:n*m网格里有蛇和障碍,蛇只能向空格处移动,不能撞到自己,问到(1,1)的最短步数,如无法到达输出-1.

关键思想:不能直接对蛇头进行BFS,因为蛇身对蛇头的决策也有影响,故BFS时应该保存蛇身状态,我们放在state里用位运算来做。因为根据蛇头和每一节延伸的方向(东南西北)我们可以还原出整条蛇。比较坑的是这道题用pow会超时,自己写一个好啦。

由于vis数组很大,如果对于每个Case都初始化vis数组浪费时间,所以在申请了全局变量vis之后,我们对于每个kase,都只用当前的kase值去标记vis表示当前状态已出现.

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

typedef long long ll;

int n,m,L,K;
int Case=1;
const int MAXN=21;
const int MAXM=21;
int M[MAXN][MAXM];
int dir[4][2]={0,1,1,0,0,-1,-1,0};
int vis[MAXN][MAXM][1<<14]={0};//蛇头在x,y的蛇状态 对应vis数组 

struct point{
    int x;
    int y;
    int step;
    int state;//二进制每两位表示一个方向(总共4个方向),共2*(L-1)位
};

int snake[10][2]; 

int POW(int a,int n){
    int x=1;
    for(int i=0;i<n;i++){
        x*=a;
    }
    return x;
}

void SnakeMap(point a){//将蛇的状态再现到地图上
    int x=a.x,y=a.y;
    int haha=3*POW(4,L-2);//位运算注意理解哦~
    int direction;
    M[x][y]=1;
    for(int i=0;i<L-1;i++){
        direction=(a.state&haha)/POW(4,L-2-i);
        M[x+=dir[direction][0]][y+=dir[direction][1]]=1;
        haha >>= 2;
    }
    return;
}

void recover(point a){//复原
    int x=a.x,y=a.y;
    int haha=3*POW(4,L-2);
    int direction;
    M[x][y]=0;
    for(int i=0;i<L-1;i++){
        direction=(a.state&haha)/POW(4,L-2-i);
        M[x+=dir[direction][0]][y+=dir[direction][1]]=0;
        haha >>= 2;
    }
    return;
}

int BFS(){
    point First;
    First.x=snake[1][0],First.y=snake[1][1],First.step=0,First.state=0;
    for(int i=2;i<=L;i++){
        if(snake[i][0]-snake[i-1][0]==1){
            First.state <<= 2;
            First.state+=1;
        }else if(snake[i][0]-snake[i-1][0]==-1){
            First.state <<= 2;
            First.state+=3;
        }else if(snake[i][1]-snake[i-1][1]==1){
            First.state <<= 2;
            First.state+=0;
        }else if(snake[i][1]-snake[i-1][1]==-1){
            First.state <<= 2;
            First.state+=2;
        }
    }//对state的处理,位运算
    vis[First.x][First.y][First.state]=Case;
    //初始化第一个格局

    queue<point>q;
    q.push(First);
    point nw,nt;
    while(!q.empty()){
        nw=q.front();
        q.pop();
        if(nw.x==1&&nw.y==1)return nw.step;
        SnakeMap(nw);//蛇状态再现在地图上
        for(int i=0;i<4;i++){
            nt.x=nw.x+dir[i][0],nt.y=nw.y+dir[i][1],nt.step=nw.step+1;
            nt.state=(nw.state/4+((i+2)%4)*POW(4,L-2));//公式是自己推的
            if(nt.x<=n&&nt.x>=1&&nt.y<=m&&nt.y>=1&&M[nt.x][nt.y]==0&&vis[nt.x][nt.y][nt.state]!=Case){
                vis[nt.x][nt.y][nt.state]=Case;
                q.push(nt);
            }
        }
        recover(nw);//还原地图
    }
    return -1;
}

int main(){
    while(scanf("%d%d%d",&n,&m,&L)==3&&(n&&m&&L)){
        memset(M,0,sizeof(M));
        memset(snake,0,sizeof(snake));

        for(int i=1;i<=L;i++){
            scanf("%d%d",&snake[i][0],&snake[i][1]);
            M[snake[i][0]][snake[i][1]]=2;
        }
        scanf("%d",&K);
        for(int i=0;i<K;i++){
            int xx,yy;
            scanf("%d%d",&xx,&yy);
            M[xx][yy]=1;
        }
        //地图输入完毕

        printf("Case %d: %d\n",Case++,BFS());
    }
    return 0;
}
时间: 2024-12-30 14:20:09

POJ 1324 [Holedox Moving] 状态压缩BFS的相关文章

poj 1324 Holedox Moving

poj 1324 Holedox Moving 题目地址: http://poj.org/problem?id=1324 题意: 给出一个矩阵中,一条贪吃蛇,占据L长度的格子, 另外有些格子是石头, 不能通过, 请问蛇到达 (1,1)格子最短距离. 明显的BFS问题, 将每一个可以走的格子进入队列, 格子判断能否走?(给蛇身体标序号(蛇头l, 蛇尾1,其他置为0), 当 fabs(cur_num - tmp_num)>=l 的时候,说明蛇的身体已经离开之前的格子了. #include <ios

POJ 1324 Holedox Moving 贪吃蛇 状态压缩 BFS

Description During winter, the most hungry and severe time, Holedox sleeps in its lair. When spring comes, Holedox wakes up, moves to the exit of its lair, comes out, and begins its new life. Holedox is a special snake, but its body is not very long.

poj 1324 Holedox Moving A*算法对bfs的优化

题意: 迷宫里有一条贪食蛇,求它的蛇头到迷宫左上角最少要多少步. 分析: 关键是将蛇的状态压缩编码,然后bfs,超时就改A*,这题有类似最短路径的性质,A*发现节点重复后不需要更新直接舍弃即可. 代码: //poj 1324 //sep9 #include <iostream> #include <algorithm> #include <queue> using namespace std; struct state { int x[10],y[10]; }; str

POJ 1753 Flip Game(状态压缩+BFS)

题目网址:http://poj.org/problem?id=1753 题目: Flip Game Description Flip game is played on a rectangular 4x4 field with two-sided pieces placed on each of its 16 squares. One side of each piece is white and the other one is black and each piece is lying ei

poj 1324 状态压缩+bfs

http://poj.org/problem?id=1324 Holedox Moving Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 17042   Accepted: 4065 Description During winter, the most hungry and severe time, Holedox sleeps in its lair. When spring comes, Holedox wakes

hdu 4771 Stealing Harry Potter&#39;s Precious (状态压缩+bfs)

Stealing Harry Potter's Precious Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1297    Accepted Submission(s): 619 Problem Description Harry Potter has some precious. For example, his invisib

胜利大逃亡(续)(状态压缩bfs)

胜利大逃亡(续) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7357    Accepted Submission(s): 2552 Problem Description Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)……这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带

POJ 3254 Corn Fields 状态压缩DP (C++/Java)

http://poj.org/problem?id=3254 题目大意: 一个农民有n行m列的地方,每个格子用1代表可以种草地,而0不可以.放牛只能在有草地的,但是相邻的草地不能同时放牛, 问总共有多少种方法. 思路: 状态压缩的DP. 可以用二进制数字来表示放牧情况并判断该状态是否满足条件. 这题的限制条件有两个: 1.草地限制. 2.相邻限制. 对于草地限制,因为输入的时候1是可以种草地的. 以"11110"草地分析,就只有最后一个是不可以种草的.取反后得00001  .(为啥取反

2014 Super Training #6 G Trim the Nails --状态压缩+BFS

原题: ZOJ 3675 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3675 由m<=20可知,可用一个二进制数表示指甲的状态,最多2^20,初始状态为0,表示指甲都没剪,然后BFS找解,每次枚举剪刀的两个方向,枚举移动的位数进行扩展状态即可. 代码: #include <iostream> #include <cstdio> #include <cstring> #include &