Holedox Moving

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;
}


 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值