2017-03-11 贪吃蛇
来源:互联网 发布:域名系统dns的作用 编辑:程序博客网 时间:2024/05/04 19:38
Description
身长为L的贪吃蛇在一个有障碍的N*M的格子中游走,问最少用多少步才能让贪吃蛇的蛇头到达(1,1)。
Input
第一行三个正整数 N, M,L。L表示贪吃蛇的长度。
接下来 L 行,顺序描述贪吃蛇每节身体的位置。每行两个正整数 X,Y。 表示某节身体的位置,按蛇头到蛇尾的顺序描述。
接下来一个正整数K。 表示有 K个障碍,每个障碍占一个格子。
接下来K行, 每行两个正整数 X,Y, 表示某个障碍的位置。
Output
一个整数,表示到达格子(1,1)最少的步数。(给定数据保证能够到达,并且蛇头移动的目标格子必须是空的。)
Sample Input
5 6 4
4 1
4 2
3 2
3 1
3
2 3
3 3
3 4
Sample Output
9
Hint
对于 100% 的数据,2≤N、M≤20,2≤L≤8
Source
搜索,A*搜索,状态压缩
Solution
直接BFS,不过这里的vis状态表示要注意。由于蛇最长为8格。所以我们用vis[21][21][1<<14] 表示蛇的这种状态是否已经出现.其中vis的前两维表示蛇头的坐标,后一维的二进制形式的每2位(可表0-3)表示从1到L-1开始该蛇的身体在该蛇身体的前一格的方向(后一格相对于前一格的方向).这样我们就能用最小的空间表示完整个蛇在迷宫的状态了.
现在要求最小距离,我们不用dist[][][]了,因为太耗空间了.我们用Node节点,Node中有x,y,st,dist 4个属性,前3个属性对应vis数组的前三维.最后一个属性是当前状态的最小距离.
在BFS扩展的时候,对于4个方向,计算得到nx和ny,然后判断nx和ny是否越界,是否是障碍,是否会与蛇的旧身体位置冲突.如果以上情况都不会发生,那么就生成了一个蛇与迷宫的新状态.
注意这里记录的st状态中的方向是指,后面一个格子(蛇的身体)处于前面一个格子(蛇的身体)的哪个方向.所以在BFS的时候,那个d要取反方向才能加到新的nst中.具体实现见代码.
思路2:对蛇身进行哈希判重,同样也要注意,下一步不能是前一个状态蛇身上的节点。http://www.cnblogs.com/yongze103/archive/2010/10/05/1843538.html
Code
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int maxr=21; const int maxc=21; int vis[maxr][maxc][1<<14];//vis第三维的高位二进制表示紧接着蛇头的那格在蛇头的相对方向 int maze[maxr][maxc]; int R,C; struct Node//注意这里记录的st状态中的方向是指,后面一个格子处于前面一个格子的哪个方向 { int x,y; int st,dist; Node(int x,int y,int st,int dist):x(x),y(y),st(st),dist(dist){} }; int L;//蛇长 int dir[10];//用来保存解码后的方向 int dx[]={1,0,-1,0};//下,左,上,右 int dy[]={0,-1,0,1}; bool check(int x,int y,Node node)//判断x,y坐标是否处于node状态的蛇身 , 下一步的蛇头 { for(int i=L-1;i>=1;i--) { dir[i]=node.st&3;//提取相对方向 node.st>>=2; } int xx=node.x,yy=node.y; for(int i=1;i<L;i++) { xx+= dx[dir[i]]; yy+= dy[dir[i]]; if(xx==x&&yy==y) return true;//表示冲突 } return false;//表示无冲突 } queue<Node> Q; int BFS(Node nod) { if(nod.x==1&&nod.y==1) return 0; while(!Q.empty())Q.pop(); Q.push(nod); vis[nod.x][nod.y][nod.st]=1; while(!Q.empty()) { Node node=Q.front();Q.pop(); int x=node.x,y=node.y,st=node.st,dist=node.dist; for(int d=0;d<4;d++) { int nx=x+dx[d],ny=y+dy[d]; if(nx==1&&ny==1) return dist+1; if(nx<1||nx>R||ny<1||ny>C||maze[nx][ny]==1||check(nx,ny,node)) continue; int ndist=dist+1,nst=(st>>2)+( ((d+2)%4)<<(2*(L-2)));//新距离,新状态,注意这里(d+2)%4表示对d取反向 if(vis[nx][ny][nst]==1)continue;//之前走过 Q.push(Node(nx,ny,nst,ndist)); vis[nx][ny][nst]=1; } } return -1; } int main() { while(scanf("%d%d%d",&R,&C,&L)==3) { if(R==0&&C==0&&L==0) break; int x,y,nx,ny; Node node(0,0,0,0); scanf("%d%d",&node.x,&node.y); x=node.x,y=node.y; for(int i=1;i<L;i++) { scanf("%d%d",&nx,&ny); for(int d=0;d<4;d++) { if(x+dx[d]==nx && y+dy[d]==ny) { node.st = (node.st<<2)+d; break; } } x=nx,y=ny; } int blocks; scanf("%d",&blocks); memset(maze,0,sizeof(maze)); for(int i=1;i<=blocks;i++) { scanf("%d%d",&x,&y); maze[x][y]=1; } printf("%d\n",BFS(node)); } return 0; }
其实,广搜也很OK
- 2017-03-11 贪吃蛇
- 【2017-2-11】贪吃蛇C++
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- 贪吃蛇
- VirtualBox is not installed. Please re-run the Toolbox Installer and try again.
- 《Python爬虫学习系列教程》学习笔记
- 扩展欧几里德算法
- 【SCOI2008】着色方案
- 安装虚拟机遇到和小红帽遇到的问题
- 2017-03-11 贪吃蛇
- 分词
- Android 与 H5-JS 简易交互
- 笔试题:字符串全排列
- javaweb_轻量级的多机同步资源解决方案
- 第一篇
- SSL 1021、洛谷 1037——产生数(dfs或高精度+Floyd)
- E/ G
- Python学习笔记-原始字符串