1.题目:Holedox Moving
2.题意:蛇从当前位置(b1:蛇头,b2、b3、b4....表示蛇身,求蛇头走到(1,1)位置最小步数,
3.解题思路:.bfs,求出最少步数,注意蛇身相当于动态石头
4.难点:处理蛇身的状态,蛇身相当于动态石头,注意蛇身前状态单独处理,不重复经过
5.wrong:
#include<stdio.h>
#include<string.h>
int visit[25][25];
struct node
{
int x,y,step,tail,head;
} Holedox[405],a[405];
int dir[4][2]= {-1,0,1,0,0,-1,0,1};
int bfs(int row, int col,int len)
{
int front=0,rear=1;
int tx,ty;
node cur,change;
Holedox[0].x=a[0].x;
Holedox[0].y=a[0].y;
Holedox[0].step=0;
while(front<rear)
{
cur=Holedox[front++];
if(cur.x==1&&cur.y==1)
return cur.step;
else
{
for(int i=0;i<4;i++)
{
tx=cur.x+dir[i][0];
ty=cur.y+dir[i][1];
if(tx>=1&&tx<=row&&ty>=1&&ty<=col&&visit[tx][ty]==0)
{
visit[tx][ty]=1;
change.x=tx;
change.y=ty;
change.step=cur.step+1;
visit[a[len-1].x][a[len-1].y]=0;
for(int i=len-2;i>=0;i--)
{
a[i+1].x=a[i].x;
a[i+1].y=a[i].y;
}
a[0].x=tx;
a[0].y=ty;
Holedox[rear++]=change;
}
}
}
}
return -1;
}
int main()
{
int row,col,len,n,tx,ty;
int cases=0;
while(scanf("%d%d%d",&row,&col,&len))
{
cases++;
memset(visit,0,sizeof(visit));
if(row==0&&col==0&&len==0)
break;
for(int i=0; i<len; i++)
{
scanf("%d%d",&tx,&ty);
a[i].x=tx;
a[i].y=ty;
visit[a[i].x][a[i].y]=1;
}
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%d%d",&tx,&ty);
visit[tx][ty]=1;
}
printf("Case %d: %d",cases,bfs(row,col,len));
}
return 0;
}
6.错误:没有处理好蛇身,可用二进制表示。因为蛇长最大为8,所以蛇身最大为7。那么蛇身最多需要2*7 = 14位 二进制数来标识。因此,我们建立三维数组visit[21][21][1<<14]来记录蛇的状态是否被访问过。建立二维数组来记录四个方向,为了以下示例的说明,直接将本程序中的记录方向的二维数组列出如下: int direct[4][2]={1,0,0,1,0,-1,-1,0}; 程序中的方向实际是由二维数组第一维的下表来标识的,如状态0即表示(1,0)(即横坐标加1,纵坐标不变,也即向右移)。注意这里的方向标识是有规律的,即左右方向的标识之和为3,上下也同样。这对于程序的执行是有影响的。
accept:
#include<iostream>
#include<string.h>
using namespace std;
int direct[4][2]= {1,0,0,1,0,-1,-1,0};
int N,M,L;
struct node
{
int x,y;
int dis;
int body;
};
bool visit[21][21][1<<14];//1<<14,左移14位
bool vis(node& t)
{
if(visit[t.x][t.y][t.body])
return true;
visit[t.x][t.y][t.body]=1;
return false;
}
bool map[20][20];
bool temp_map[20][20];
bool valid(int x,int y)
{
if(x<0||x>=N||y<0||y>=M||temp_map[x][y]) return false;
return true;
}
node Q[20*20*(1<<14)];
int head,tail;
int Bfs()
{
int x,y,lx,ly,i,k,nx,ny;
node t;
node now;
memset(visit,0,sizeof(visit));
cin>>lx>>ly;
t.x=lx-1;
t.y=ly-1;
t.dis=0;
t.body=0;
for(i=1; i<L; i++)
{
cin>>x>>y;
for(k=0; k<4; ++k)
if(lx+direct[k][0]==x&&ly+direct[k][1]==y)
break;
t.body|=k<<((i-1)<<1);
lx=x;
ly=y;
}
memset(map,0,sizeof(map));
cin>>k;
for(i=0; i<k; i++)
{
cin>>x>>y;
map[x-1][y-1]=1;
}
head=tail=0;
Q[tail++]=t;
vis(t);
while(head!=tail)
{
now=Q[head++];
if(now.x==0&&now.y==0)return now.dis;
memcpy(temp_map,map,sizeof(map));
temp_map[x=now.x][y=now.y]=1;
int s=now.body;
for(i=1; i<L; i++,s>>=2)
{
k=s&3;
temp_map[x=x+direct[k][0]][y=y+direct[k][1]]=1;
}
for(k=0; k<4; k++)
{
if(!valid(nx=now.x+direct[k][0],ny=now.y+direct[k][1]))
continue;
t.x=nx;
t.y=ny;
t.body=((now.body<<2)|(3-k))&((1<<((L-1)<<1))-1);
t.dis=now.dis+1;
if(!vis(t))
{
Q[tail++]=t;
}
}
}
return -1;
}
int main()
{
int Cas=0;
while(cin >> N >> M >> L)
{
if(N==0&&M==0&&L==0)break;
cout<<"Case "<<++Cas<<": "<<Bfs()<<endl;
}
return 0;
}