Codeforces 225D Snake(状压BFS)

来源:互联网 发布:php二分查找算法 编辑:程序博客网 时间:2024/06/07 23:25

传送门:http://codeforces.com/problemset/problem/225/D
题意:有一条蛇,头是1,然后按照234……的顺序趴在一个图上,问你蛇最少几步能吃到@。
思路:这题还是挺简单的,因为只要想到如何去保存蛇的状态就能做了。因为这题其实就是一个BFS,但是在BFS的过程中,你要知道这个蛇的当前状态是怎么样的。如果直接从1开始BFS,不管其余部位的话,在走了几步之后,蛇的剩余部位移动了以后就很难判断。
所以我们就可以想到,状压一条蛇。把一条蛇的形状状态压缩成三个数字。两个数字表示蛇头的x,y,剩下一个status用来保存蛇的剩余位置,但是由于每个位置都很难用一个数字保存。所以我们就可以想到保留相对位置,因为相对位置只有4种,上下左右,所以可以用二进制00,01,10,11来保存。假设一个蛇的长度为len,那么我们只要用(len-1)*2的一个二进制数来保存每个位置相对于他的上一个位置的数字。然后在每一次BFS的时候,将蛇的status左移两格,然后|=它的新位置的相对位置,再判断一下是否跟蛇的其他部位碰撞了。然后用一个vis[x][y][status]来保存当前位置是否访问过了,就可以轻松AC了。

#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <cstdlib>#include <cctype>#include <string>#include <iostream>#include <vector>#include <map>#include <set>#include <queue>#include <ctime>using namespace std;typedef long long ll;typedef pair<int,int> pii;#define pb push_back#define mp make_pair#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define calm (l+r)>>1const int INF=2139062143;const int maxn=20;int n,m,maxlen;ll base;char pic[maxn][maxn];bool vis[15][15][65536];int go[4][2]={{1,0},{-1,0},{0,1},{0,-1}};int rev[4][2]={{-1,0},{1,0},{0,-1},{0,1}};struct snake{    int x,y;    int status;    snake():x(0),y(0),status(0){}}start;inline bool judge(int x,int y){    return x>=0&&x<n&&y>=0&&y<m;}void startpos(){//计算出一开始蛇的状态,和一些其他数据    maxlen=0;    int x,y;    for(int i=0;i<n;i++){        for(int j=0;j<m;j++)if(pic[i][j]!='#'&&pic[i][j]!='@'){            if(pic[i][j]-'0'>maxlen){                x=i;y=j;                maxlen=pic[i][j]-'0';            }            if(pic[i][j]=='1'){                start.x=i;start.y=j;            }        }    }    base=(1<<((maxlen-1)*2))-1;//蛇的最大长度所需要的全1二进制数,用来去掉多余位置的数据    int &status=start.status;    status=0;    while(pic[x][y]!='1'){        for(int i=0;i<4;i++){            int xx=x+rev[i][0],yy=y+rev[i][1];            if(judge(xx,yy)&&pic[xx][yy]==pic[x][y]-1){                status<<=2;                status|=i;                x=xx;y=yy;                break;            }        }    }}#define F first#define S secondbool bomb(int xx,int yy,snake s){//从蛇头开始移动,并判断是否发生碰撞    int &status=s.status;    int x=s.x,y=s.y;    if(x==xx&&y==yy)return false;    for(int i=1;i<maxlen-1;i++){        x+=go[status&3][0];        y+=go[status&3][1];        status>>=2;        if(x==xx&&y==yy)return false;    }    return true;}int BFS(){    queue<pair<snake,int>> Q;    Q.push(mp(start,0));    vis[start.x][start.y][start.status]=true;    while(!Q.empty()){        snake st=Q.front().F;        int step=Q.front().S;        if(pic[st.x][st.y]=='@')return step;        Q.pop();        for(int i=0;i<4;i++){            int xx=st.x+rev[i][0];            int yy=st.y+rev[i][1];            if(judge(xx,yy)&&pic[xx][yy]!='#'&&bomb(xx,yy,st)){                snake next;                next.x=xx;next.y=yy;                next.status=((st.status<<2)&base)|i;                if(!vis[xx][yy][next.status]){                    vis[xx][yy][next.status]=true;                    Q.push(mp(next,step+1));                }            }        }    }    return -1;}int main(){    //freopen("D://input.txt","r",stdin);    scanf("%d%d",&n,&m);    for(int i=0;i<n;i++){        scanf("%s",pic[i]);    }    startpos();    printf("%d\n",BFS());    return 0;}
0 0
原创粉丝点击