搜索~贪吃蛇简化
大意: 给你一个矩阵,有一条蛇,问蛇走到(1,1)点所需要的步骤数,有石块障碍
思路:
被这道题的状态如何标记折磨了两天~,后来看老师讲稿,队里大牛讲解终于搞懂了; 蛇的长度[1,8]。矩阵大小不超过20*20。蛇头的每一次移动蛇身就会跟着移动,所以一般的在地图标记蛇身的一节需要[21][21]数组, 蛇身最长有8节,也就是16维数组。怎么开的了。。。。
优化标记状态:(这想法妙~)
蛇相连的两节之间的X,Y之差只有四种可能:(0,1) (-1,0) (0,-1) (1,0) 给它们都+1 就成了一个[3][3]数组完全放的下,然后记+1后的 [0][1]=0; [1][0]=1; [1][2]=2; [2][1]=3; 就可以用四进制来表示蛇的最大状态不会超过 3*(4^8) < (10^6) 这样就可以接受了~及标记状态数组只要[21][21][10^6] 就ok~~~~
#include<iostream> #include<cstring> #include<cstdio> using namespace std; const int MAXN = 16384; const int MAX = 5000000; struct node { int x[8][2]; int step; } Q[MAX]; bool map[21][21], v[21][21][MAXN]; int t[3][3]; //对于状态的压缩所用的数组 int dir[4][2] = {0, 1, -1, 0, 0, -1, 1, 0}; int n, m, l; int BFS(int len[8][2]) { int front=0, last=0; //模拟循环队列头尾 int x, y, i, j, sum; x=len[0][0]; y=len[0][1]; for(sum=0, i=1; i<l; i++) { sum = sum*4+t[x-len[i][0]+1][y-len[i][1]+1]; x = len[i][0]; y = len[i][1]; } v[len[0][0]][len[0][1]][sum]=true; //标记起始位置 for(i=0; i<l; i++) { Q[last].x[i][0]=len[i][0]; Q[last].x[i][1]=len[i][1]; } Q[last].step=0; last = (last+1) % MAX; while(front!=last) { if(Q[front].x[0][0]==1 && Q[front].x[0][1]==1) //到达目标 return Q[front].step; for(i=0; i<4; i++) { x = Q[front].x[0][0] + dir[i][0]; y = Q[front].x[0][1] + dir[i][1]; if(x<1 || x>n || y<1 || y>m) continue; //越界 int flag=0; //判断是否为本身 flag为标记 for(j=0; j<l; j++) if(x==Q[front].x[j][0] && y==Q[front].x[j][1]) { flag=1; break; } if(map[x][y] || flag) continue; //石头或者本身 int tx=x, ty=y; for(sum=0, j=0; j<l-1; j++) { sum = sum*4+t[tx-Q[front].x[j][0]+1][ty-Q[front].x[j][1]+1]; tx = Q[front].x[j][0]; ty = Q[front].x[j][1]; } if(v[x][y][sum]) continue; //新的位置是否被标记过 v[x][y][sum] = true; Q[last].x[0][0]=x; Q[last].x[0][1]=y; for(j=1; j<l; j++) //更新蛇身 { Q[last].x[j][0]=Q[front].x[j-1][0]; Q[last].x[j][1]=Q[front].x[j-1][1]; } Q[last].step = Q[front].step+1; last=(last+1)%MAX; //修改指针 } front=(front+1)%MAX; } return -1; } int main() { int cas=1, i, j, k, len[8][2]; t[0][1]=0; t[1][0]=1; t[1][2]=2; t[2][1]=3; //对于x,y坐标的差值各自+1 就有这四种结果 while(scanf("%d%d%d", &n, &m, &l)&& n && m && l) { for(i=1; i<=n; i++) for(j=1; j<=m; j++) { map[i][j]=false; for(k=0; k<=MAXN; k++) v[i][j][k]=false; } for(i=0; i<l; i++) scanf("%d%d", &len[i][0], &len[i][1]); scanf("%d", &k); while(k--) { scanf("%d%d", &i, &j); map[i][j]=true; } k = BFS(len); printf("Case %d: %d\n", cas++, k); } return 0; }

浙公网安备 33010602011771号