用到算法:BFS,二进制优化
吐槽:写了三天的题我也是醉了
经验:使用了大量的输出用来调试代码,最后发现只要把贪食蛇用图像的方式显示出贪食蛇的行走路径就能发现问题所在。
学到的新东西:
1.用二进制表示搜索中动态的障碍物
2.使用辅助数组如本题direct。一来方便遍历周围方向,二来可以存储动态障碍。
3.辅助数组采取一定规则设计。比如本题,对角元素的下标加起来为3.
本题思路:
贪食蛇的头为移动点,身体为不固定障碍,石头为固定障碍。存储移动点及固定障碍,用其来判断一个状态是否访问过。难点在如何表示不固定障碍及遍历方向后如何更新状态。当然也很难想哈哈哈。
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <queue>
#include <algorithm>
using namespace std;
int n,m,l;
struct node
{
int x,y,step,body;
}snake;
int visit[20][20][1<<14];
int direct[4][2] ={{-1,0},{0,1},{0,-1},{1,0}};
int map[20][20];
int tmap[20][20];
bool vis(node a)
{
if(visit[a.x][a.y][a.body])
return true;
visit[a.x][a.y][a.body] = 1;
return false;
}
bool valid(node a)
{
if(a.x>=n || a.x<0 || a.y>=m || a.y<0 || tmap[a.x][a.y])
return false;
if(vis(a))
return false;
return true;
}
int bfs()
{
memset(map, 0 , sizeof(map));
memset(visit, 0, sizeof(visit));
int tx,ty;
int x,y;
scanf("%d%d", &tx, &ty);
snake.x = tx-1;
snake.y = ty-1;
snake.step = 0;
snake.body = 0;
int i,j;
for(i=1; i<l; i++)
{
scanf("%d%d", &x, &y);
for(j=0; j<4; j++)
if(direct[j][0]==x-tx && direct[j][1]==y-ty)
break;
//printf("now j is %d ",j);
snake.body = snake.body<<2 | j;
//printf("now the body is %d\n",snake.body);
tx=x; ty=y;
}///010011=1+2+16=19 000110=2+4=6
//printf("snake's body is %d\n", snake.body);
int k;
scanf("%d", &k);
for(i=0; i<k; i++)
{
scanf("%d%d", &x, &y);
map[--x][--y] = 1;
}
///***init***///
queue <node> q;
q.push(snake);
while(!q.empty())
{
node t = q.front();
//printf("t.x = %d t.y = %d t.body = %d t.step = %d\n",t.x+1,t.y+1,t.body,t.step);
if(t.x == 0 && t.y == 0)
return t.step;
//printf("x=%d,y=%d,step=%d\n",t.x+1,t.y+1, t.step);
memcpy(tmap, map, sizeof(map));
x = t.x;
y = t.y;
tmap[x][y] = 1;
int f = t.body;
//int sum=0;
for(i=l-2; i>=0;i--)
{
k=3&f>>(2*i);
//printf("now k is %d\n",k);
x = x+direct[k][0];
y = y+direct[k][1];
tmap[x][y] = 1;
//printf("%d\n",sum++);
}
/*for(i=0; i<n; i++)
{
for(j=0; j<m; j++)
printf("%d ",tmap[i][j]);
printf("\n");
}
printf("\n");*/
//printf("t's location is %d and %d\n", t.x, t.y);
for(i=0; i<4; i++)
{
node temp;
temp.x = t.x+direct[i][0];
temp.y = t.y+direct[i][1];
temp.step = t.step+1;
//printf("t.body>>2 = %d\n",t.body>>2);
temp.body = (t.body>>2) | (3-i)<<2*(l-2);
//printf("t.body = %d, temp.body = %d\n",t.body,temp.body);
if(valid(temp))
{
//printf("now i is %d\n",i);
q.push(temp);
//printf("now t's next state is %d\n",temp.body);
}
}
q.pop();
}
return -1;
}
int main()
{
int cas = 1;
//printf("%d\n",3<<6);
while(scanf("%d%d%d", &n, &m, &l)!=EOF && n && m && l)
{
printf("Case %d: %d\n",cas++, bfs());
}
return 0;
}