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
- Codeforces 225D Snake(状压BFS)
- Codeforces 225D Snake 位运算hash + bfs
- Codeforces Round #139 (Div. 2) D. Snake
- Codeforces Round #139 (Div. 2) D. Snake
- CodeForces 586D【BFS】
- Codeforces 796D bfs
- codeforces 676D (bfs 模拟)
- (BFS)codeforces #Round354-div2-D
- Codeforces Fox And Snake
- Codeforces 463D Gargari and Permutations(BFS)
- Codeforces 467D Fedor and Essay bfs
- Codeforces 467D Fedor and Essay(bfs)
- Codeforces--192.div2.D Biridian Forest bfs
- codeforces 553D Nudist Beach 二分+bfs
- codeforces 354D. Theseus and labyrinth bfs
- Codeforces #354D (Div. 2) 暴力BFS
- Codeforces Round #325 (Div. 2) D bfs
- Codeforces Round #375 (Div. 2) D bfs
- 支付宝支付
- 取石子问题
- target XXX do ->end 常见问题
- 浅谈Java设计模式(十九)备忘录模式(Memento)
- libcurl CURLOPT_WRITEFUNCTION注意事项
- Codeforces 225D Snake(状压BFS)
- eclipse远程调试Tomcat方法(测试成功并且说说遇到的坑)
- IOS 开发大牛首选之路
- HDFS的Block数据balancer重分布实战
- JQUERY弹出层 三种弹出效果
- RTMP协议分析
- 杂
- c/c++static关键字
- Promise对象