pku 1324 Holedox Moving
题目地址: http://acm.pku.edu.cn/JudgeOnline/problem?id=1324
题目大意:
给你一个由小方格构成的“蛇身”,对蛇的头部和身子部分进行了排号,终点为矩阵左上角的第一个点,矩阵中有的点被标记了不可访问点,问蛇是否能通过移动进而使蛇头到达终点,如果可以的话,输出所要的最小步数。
具体分析:
简单点一下,以后会具体分析。这边蛇的移动的本质,就是后面的点替代前面的点的过程。还有一个最难的地方,就是如何存储蛇的状态,避免BFS重复搜索,避免TLE,如果用数组存储蛇身的话,在判断现在位置的蛇是否出现的话,会出现超时,所以要用状态压缩来存储蛇的状态,然后BFS。
AC代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
using namespace std;
#define N 25
bool vis[N][N][1<<14];
int dirc[4][2] = {{1,0},{-1,0},{0,-1},{0,1}};
int s_x[N],s_y[N];
int Map[N][N];
int n,m,k,l,ans;
struct Node
{
int x, y;
int sum;
int cnt;
Node(int x = 0):cnt(x){}
};
int get_dirc(int x ,int y)
{
if(x == 1&& y ==0)
return 0;
if(x == -1 && y== 0)
return 1;
if(x==0 && y== -1)
return 2;
if(x == 0 && y== 1)
return 3;
}
int check(Node& T, int pos_x, int pos_y)
{
int sum ,temp, x, y;
sum = T.sum;
x = T.x;
y = T.y;
for(int i= 1 ;i <l ;i++)//坑点在这里,由于最后一个点被遗弃,新的蛇头点可以占用其位置,并不用一定要与之不同
{
temp = sum&3;
sum >>=2;
x += dirc[temp][0];
y += dirc[temp][1];
// printf("(%d %d)\n",x ,y);
if(pos_x== x && pos_y== y)
return 0;
}
T.sum = T.sum %( 1 << ((l-1-1)*2) );
T.sum = T.sum*4 + get_dirc(T.x - pos_x, T.y - pos_y);
T.x = pos_x;
T.y = pos_y;
if(vis[T.x][T.y][T.sum])
return 0;
vis[T.x][T.y][T.sum] =1;
T.cnt++;
return 1;
}
void BFS(Node& T)
{
queue<Node> q;
Node temp,Front;
temp = Front = T;
q.push(temp);
while(!q.empty())
{
Front = q.front();
q.pop();
if(Front.x == 1 && Front.y == 1)
{
ans = Front.cnt;
return ;
}
for(int i = 0 ;i < 4 ;i++)
{
temp = Front;
int x = temp.x + dirc[i][0];
int y = temp.y + dirc[i][1];
if(x>=1 && x<=n && y>=1 && y<=m && !Map[x][y]&& check(temp,x,y))
q.push(temp);
}
}
return ;
}
int main()
{
int Case = 0;
while(cin >> n >> m >> l)
{
if(!n && !m && !l)
break;
Case++;
ans = -1;
memset(Map,0,sizeof(Map));
memset(vis,false,sizeof(vis));
for(int i = 0 ;i < l ;i++)
cin >> s_x[i] >> s_y[i];
int sum = 0;
for(int i = l-1 ; i >=1 ; i--) //4进制方向转化为10进制方向进行存储
sum = sum*4 + get_dirc(s_x[i] - s_x[i-1], s_y[i] - s_y[i-1]);
cin >> k;
int a, b;
for(int i = 0 ;i < k ;i++)
{
cin >> a >> b;
Map[a][b] = 1;
}
Node First;
First.x = s_x[0] , First.y = s_y[0];
First.sum = sum;
vis[First.x][First.y][sum] =1;
BFS(First);
printf("Case %d: %d\n",Case,ans);
}
return 0;
}