朴素暴力方法做的。。。
用 一个1 2 3 4表示 当前蛇身与 上一部分蛇身的位置关系,蛇最长为7,所以可以 用 4进制 表示状态,每一个蛇头 ,其蛇身有 4^7种状态
用状态压缩 标记出现过的状态,,以免重复计算TLE。。。。
别的地方就是朴素的BFS。。。。
写得太挫。。状态数组要开 bool才能过,不然tle
当然本题还可以用双向bfs,A*算法。。。
在朴素算法的基础上用bitset表示状态 节省了空间 3000kb,时间还是差不多 3.8s
以下是朴素方法 : 3.9s... 10520kb
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
struct node
{
int hx,hy;
int body[8]; //1 2 3 4 分别代表上下左右
int step;
};
int len;
int n,m,l;
queue<node> qq;
int dirx[]={0,0,1,-1}; //you zuo xia shang
int diry[]={1,-1,0,0};
int mp[22][22];
bool state[22][22][1<<14];
int trans(int x,int y) //计算del_x,del_y代表的方位
{
if (x==-1&&y==0)
return 1; //shang
if (x==1&&y==0)
return 2; //下
if (x==0&&y==-1)
return 3 ; //左
if (x==0&&y==1)
return 4; //右
}
node move_to(node t,int x,int y) //蛇移动到[X,Y]后整体坐标的变化
{
node res;
int i;
for (i=len;i>1;i--)
{
res.body[i]=t.body[i-1];
}
int dir=trans(t.hx-x,t.hy-y);
res.body[1]=dir;
res.step=t.step+1;
res.hx=x;
res.hy=y;
return res;
}
inline void get_xy(int &tx,int &ty,int dir,int x,int y) //得到坐标值
{
if (dir==1)//上
{
tx=x-1;ty=y;
}
if (dir==2)//xia
{
tx=x+1;ty=y;
}
if (dir==3)//zuo
{
tx=x;ty=y-1;
}
if (dir==4)//you
{
tx=x;ty=y+1;
}
return ;
}
void deal_map(node t) //把蛇身标记为障碍
{
int i;
int lastx,lasty;
for (i=1;i<=len;i++)
{
int tx,ty;
if (i==1)
{
get_xy(tx,ty,t.body[i],t.hx,t.hy);
}
else
{
get_xy(tx,ty,t.body[i],lastx,lasty);
}
lastx=tx;
lasty=ty;
if (mp[tx][ty]==0)
mp[tx][ty]=2;
}
}
void un_deal_map(node t) //去掉 蛇身记号
{
int i;
int lastx,lasty;
for (i=1;i<=len;i++)
{
int tx,ty;
if (i==1)
{
get_xy(tx,ty,t.body[i],t.hx,t.hy);
}
else
{
get_xy(tx,ty,t.body[i],lastx,lasty);
}
lastx=tx;
lasty=ty;
if (mp[tx][ty]==2)
mp[tx][ty]=0;
}
}
int get_body_num(node &y) //计算该状态特征值
{
int i;
int ret=0;
for (i=1;i<=len;i++)
{
// ret+=(y.body[i]-1)* int(pow(4.0,i-1)); 下一行与本行等价
ret+=(y.body[i]-1)* 1<<(2*(i-1)) ; //位运算加速
}
return ret;
}
int main()
{
int cnt=1;
while(scanf("%d%d%d",&n,&m,&l)!=EOF)
{
if (!n&&!m&&!l) break;
while(!qq.empty())
qq.pop();
node tm;
memset(mp,0,sizeof(mp));
memset(state,0,sizeof(state));
int i;
scanf("%d%d",&tm.hx,&tm.hy);
for (i=0;i<=m+1;i++) //lock the board 边界设置为障碍
mp[0][i]=1;
for (i=0;i<=m+1;i++)
mp[n+1][i]=1;
for (i=0;i<=n+1;i++)
mp[i][0]=1;
for (i=0;i<=n+1;i++)
mp[i][m+1]=1;
int xx,yy;
int lastx,lasty;
int delx,dely;
for (i=1;i<=l-1;i++)
{
scanf("%d%d",&xx,&yy);
if (i==1)
{
delx=xx-tm.hx;
dely=yy-tm.hy;
}
else
{
delx=xx-lastx;
dely=yy-lasty;
}
tm.body[i]=trans(delx,dely); //记录每个部分是在前一部分的什么方向
lastx=xx;
lasty=yy;
}
len=l-1;
int num;
scanf("%d",&num);
for (i=1;i<=num;i++)
{
scanf("%d%d",&xx,&yy);
mp[xx][yy]=1; //屏蔽障碍
}
tm.step=0;
int ret=get_body_num(tm);
state[tm.hx][tm.hy][ret]=true;
qq.push(tm);
int ans=-1;
while(!qq.empty())
{
node t=qq.front();
qq.pop();
if (t.hx==1&&t.hy==1) //结束条件
{
ans=t.step;
break;
}
deal_map(t); //设蛇身为障碍
for (i=0;i<4;i++)
{
int x=t.hx+dirx[i];
int y=t.hy+diry[i];
if (mp[x][y]) continue; //如果不可行
node res=move_to(t,x,y); //移动后得到的新状态res
int ret=get_body_num(res); //计算是否出现过当前状态
if (state[res.hx][res.hy][ret]==true)
continue;
state[res.hx][res.hy][ret]=true;
qq.push(res);
}
un_deal_map(t); //恢复地图
}
printf("Case %d: %d\n",cnt++,ans);
}
return 0;
}