• POJ 1324 Holedox Moving(我已经努力了。。)



    参考了:

    poj 1324 简化的贪吃蛇

    在周同学的帮助下,加了个优化,总算过了,先说一下做法:
    1、宽搜是必要的,那么如何记录蛇当前的状态,以避免以后重复的访问变成了关键,在这里我们将蛇的状态描述为如下三元组(x,y,state),其中(x,y)是蛇头的坐标,state记录的是尾巴的状态,由于尾巴最长为七段,每一段相对于前一段只有上下左右四种状态,仅需要两位表示,则尾巴状态最多需要7×2=14位二进制数表示,则我们可以构建矩阵pMatrix[21][21][16384]来保存访问过的状态,以避免重复访问相同的状态,后面的工作就是传统的宽搜过程了;
    2、如果仅按上面的方法来做的话会超时,于是加入了下面的减枝优化。即先不考虑蛇尾,使用宽搜算出仅蛇头一段从初始点走到结束点所需要的最少步数minstep,然后将蛇尾的初始位置看作石块,再用宽搜算出仅蛇头从初始点走到结束点所需要的最少步数maxstep,这里可以证明所要求的最小步数就在区间[minstep,maxstep]内,如果minstep==maxstep,则该值就是所求值,如果minstep不存在(不可达),则所求蛇的路径也不存在,(这里有一点要说明的是,即使maxstep不存在,也不能说明所求最短路径不存在,因为求maxstep时将蛇尾看作固定的障碍物,而实际情况下,蛇尾会随蛇头运动,会使求maxstep过程中不可行的路径变为可行。)否则,我们就执行1里定义的宽搜过程,在宽搜过程中,当已走的步数加上从当前点到终点的最短距离(x坐标+y坐标)大于maxstep时,就不再考虑此路径,如此达到减枝提速的目的。
    3、maxstep是上限可以这么理解:当将尾巴看作固定的障碍时,从头到终点要绕过尾巴,而实际情况下,尾巴随头移动,故要绕开尾巴所要走的步数<=固定尾巴时的情况,又只有在初始情况下,尾巴可能会出现在头所要走的路径的前方,需要绕开,在第一次绕开之后,尾巴就一直跟在头后面了,不会再成为障碍物,与没尾巴时的情况一样,因此maxstep即是步数的上限。
    但还是TLE,估计是STL队列效率低的原因


    #include <iostream>
    #include <string.h>
    #include <string>
    #include <cmath>
    #include <queue>

    #define INF 1999999999

    using namespace std;

    struct SNote
    {
        int len;
        int SnakeX[8];//蛇 结点 和 位置  0号是头
        int SnakeY[8];
        int spa;
        int deepth;
    };

    struct poi
    {
        int x;
        int y;
        int deepth;
    }P;

    int MAXss;
    int MINss;

    int Map[22][22];

    int vis[21][21][16400];

    queue<SNote> q;

    int tovis(SNote sn)
    {
        string msg;
        for(int i=0;i<sn.len-1;i++)
        {
            if(sn.SnakeX+1==sn.SnakeX[i+1]&&sn.SnakeY==sn.SnakeY[i+1])//  shang
            {
                msg+="10";
            }
            else if(sn.SnakeX-1==sn.SnakeX[i+1]&&sn.SnakeY==sn.SnakeY[i+1])//xia
            {
                msg+="11";
            }
            else if(sn.SnakeY-1==sn.SnakeY[i+1]&&sn.SnakeX==sn.SnakeX[i+1])//zuo
            {
                msg+="00";
            }
            else if(sn.SnakeY+1==sn.SnakeY[i+1]&&sn.SnakeX==sn.SnakeX[i+1])//you
            {
                msg+="01";
            }
        }
       // cout<<msg<<endl;

        int sum=0;
        for(int i=0;i<msg.length();i++)
        {
            if(msg=='1')
                sum+=pow(2,i);
        }
        if(vis[sn.SnakeX[0]][sn.SnakeY[0]][sum]==0)
        {
            vis[sn.SnakeX[0]][sn.SnakeY[0]][sum]=1;
            return 1;
        }
        else return 0;
    }

    int _bfs()
    {
        SNote b;
        while(!q.empty())
        {
            b=q.front();
            q.pop();
        int m[22][22];
        for(int i=0;i<22;i++)
            for(int j=0;j<22;j++)
               m[j]=Map[j];
        SNote a=b;
        for(int i=0;i<a.len;i++)
        {
            if(i==0)
                m[b.SnakeX][b.SnakeY]=3;
            else
                m[b.SnakeX][b.SnakeY]=2;
        }
        if(m[1][1]==3)
        {
            return b.deepth;
        }
        else
        {
        //go up
        a=b;
        if(m[a.SnakeX[0]-1][a.SnakeY[0]]==0&&(a.deepth+a.SnakeX[0]-1+a.SnakeY[0]-2)<=MAXss)
        {
            int ac,bc;
            ac=a.SnakeX[0]; bc=a.SnakeY[0];
            for(int i=1;i<a.len;i++)
            {
                swap(ac,a.SnakeX);
                swap(bc,a.SnakeY);
            }
            a.SnakeX[0]=a.SnakeX[0]-1;

            if(tovis(a))
            {
       //                cout<<"可以向up移动"<<endl;
            a.deepth=b.deepth+1;
            q.push(a);
            }
            else  ;
        }
        //go down
        a=b;
        if(m[a.SnakeX[0]+1][a.SnakeY[0]]==0&&(a.deepth+a.SnakeX[0]+1+a.SnakeY[0]-2)<=MAXss)
        {
            int ac,bc;
            ac=a.SnakeX[0]; bc=a.SnakeY[0];
            for(int i=1;i<a.len;i++)
            {
                swap(ac,a.SnakeX);
                swap(bc,a.SnakeY);
            }
            a.SnakeX[0]=a.SnakeX[0]+1;
          if(tovis(a))
            {
      //            cout<<"可以向down移动"<<endl;
            a.deepth=b.deepth+1;
            q.push(a);
            }
            else  ;
        }
        //go right
        a=b;
        if(m[a.SnakeX[0]][a.SnakeY[0]+1]==0&&(a.deepth+a.SnakeX[0]+a.SnakeY[0]-1)<=MAXss)
        {
            int ac,bc;
            ac=a.SnakeX[0]; bc=a.SnakeY[0];
            for(int i=1;i<a.len;i++)
            {
                swap(ac,a.SnakeX);
                swap(bc,a.SnakeY);
            }
            a.SnakeY[0]=a.SnakeY[0]+1;
           if(tovis(a))
            {
      //                 cout<<"可以向right移动"<<endl;
            a.deepth=b.deepth+1;
            q.push(a);
            }
            else  ;
        }
        //go left
        a=b;
        if(m[a.SnakeX[0]][a.SnakeY[0]-1]==0&&(a.deepth+a.SnakeX[0]+a.SnakeY[0]-3)<=MAXss)
        {

            int ac,bc;
            ac=a.SnakeX[0]; bc=a.SnakeY[0];
            for(int i=1;i<a.len;i++)
            {
                swap(ac,a.SnakeX);
                swap(bc,a.SnakeY);
            }
            a.SnakeY[0]=a.SnakeY[0]-1;
             if(tovis(a))
            {
      //                 cout<<"可以向left移动"<<endl;
            a.deepth=b.deepth+1;
            q.push(a);
            }
            else  ;
        }
        }
        }
        return -1;
    }

    int _bfsMAX(SNote &sn)
    {

        int MMMp[22][22];
        int vivis[22][22];
        for(int i=0;i<22;i++)
        {
            for(int j=0;j<22;j++)
                vivis[j]=MMMp[j]=Map[j];
        }
        for(int i=1;i<sn.len;i++)
        {
            MMMp[sn.SnakeX][sn.SnakeY]=1;
            vivis[sn.SnakeX][sn.SnakeY]=1;
        }

        P.x=sn.SnakeX[0];  P.y=sn.SnakeY[0];
        P.deepth=0;
        queue<poi> qt;
        qt.push(P);
        while(!qt.empty())
        {
            poi K,L;
            L=K=qt.front();
            qt.pop();
            if(K.x==1&&K.y==1)
            {
                return K.deepth;
            }
            else
            {
                K=L;
                // go up
                if(MMMp[K.x-1][K.y]==0&&vivis[K.x-1][K.y]==0)
                {
                    //cout<<"let's go up\n";
                    K.x=K.x-1;
                    vivis[K.x][K.y]=1;
                    K.deepth=K.deepth+1;
                    qt.push(K);
                }
                K=L;
                //go down
                if(MMMp[K.x+1][K.y]==0&&vivis[K.x+1][K.y]==0)
                {
                    //cout<<"let's go down\n";
                    K.x=K.x+1;
                    vivis[K.x][K.y]=1;
                    K.deepth=K.deepth+1;
                    qt.push(K);
                }
                K=L;
                //go left
                if(MMMp[K.x][K.y-1]==0&&vivis[K.x][K.y-1]==0)
                {
                    K.y=K.y-1;
                    vivis[K.x][K.y]=1;
                    K.deepth=K.deepth+1;
                    qt.push(K);
                }
                K=L;
                //go right
                 if(MMMp[K.x][K.y+1]==0&&vivis[K.x][K.y+1]==0)
                {
                    K.y=K.y+1;
                    vivis[K.x][K.y]=1;
                    K.deepth=K.deepth+1;
                    qt.push(K);
                }
            }
        }

        return INF;
    }

    int _bfsNIN(SNote &sn)
    {
        int MMMp[22][22];
        int vivis[22][22];
        for(int i=0;i<22;i++)
        {
            for(int j=0;j<22;j++)
                vivis[j]=MMMp[j]=Map[j];
        }
        P.x=sn.SnakeX[0];  P.y=sn.SnakeY[0];
        P.deepth=0;
        queue<poi> qt;
        qt.push(P);
        while(!qt.empty())
        {
            poi K,L;
            L=K=qt.front();
            qt.pop();
            if(K.x==1&&K.y==1)
            {
                return K.deepth;
            }
            else
            {
                K=L;
                // go up
                if(MMMp[K.x-1][K.y]==0&&vivis[K.x-1][K.y]==0)
                {
                    //cout<<"let's go up\n";
                    K.x=K.x-1;
                    vivis[K.x][K.y]=1;
                    K.deepth=K.deepth+1;
                    qt.push(K);
                }
                K=L;
                //go down
                if(MMMp[K.x+1][K.y]==0&&vivis[K.x+1][K.y]==0)
                {
                    //cout<<"let's go down\n";
                    K.x=K.x+1;
                    vivis[K.x][K.y]=1;
                    K.deepth=K.deepth+1;
                    qt.push(K);
                }
                K=L;
                //go left
                if(MMMp[K.x][K.y-1]==0&&vivis[K.x][K.y-1]==0)
                {
                    K.y=K.y-1;
                    vivis[K.x][K.y]=1;
                    K.deepth=K.deepth+1;
                    qt.push(K);
                }
                K=L;
                //go right
                 if(MMMp[K.x][K.y+1]==0&&vivis[K.x][K.y+1]==0)
                {
                    K.y=K.y+1;
                    vivis[K.x][K.y]=1;
                    K.deepth=K.deepth+1;
                    qt.push(K);
                }
            }
        }
        return INF;

    }

    int main()
    {
        int tot=0;

        int m,n,c;
     while(cin>>n>>m>>c&&m!=0&&c!=0&&n!=0)
     {
         SNote sn;
        tot++;
        memset(Map,0,sizeof(Map));
        memset(vis,0,sizeof(vis));
        for(int i=0;i<=m+1;i++)
        {
            Map[0]=1;
            Map[n+1]=1;
        }
        for(int i=0;i<=n+1;i++)
        {
            Map[0]=1;
            Map[m+1]=1;
        }
        sn.len=c;
        for(int i=0;i<c;i++)
        {
            cin>>sn.SnakeX>>sn.SnakeY;
        }
        sn.deepth=0;

        int k;
        cin>>k;
        for(int i=0;i<k;i++)
        {
            int a,b;
            cin>>a>>b;
            Map[a]=1;
        }

        q.push(sn);

        MAXss=_bfsMAX(sn);
        MINss=_bfsNIN(sn);
     //   cout<<MAXss<<endl;
        if(MINss==MAXss)  cout<<"Case "<<tot<<": "<<MINss<<endl;
        else if(MINss==INF)  cout<<"Case "<<tot<<": "<<-1<<endl;
        else
        cout<<"Case "<<tot<<": "<<_bfs()<<endl;
        while(!q.empty())
            q.pop();

     }
        return 0;
    }




    贴一个可以AC的:(想抄的就去抄吧)
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <string>
    #include <cmath>
    #include <cstring>
    #include <queue>
    #include <set>
    #include <vector>
    #include <stack>
    #include <map>
    #include <iomanip>
    #define PI acos(-1.0)
    #define Max 2005
    #define inf 1<<28
    using namespace std;

    int n,m,k;
    struct snake
    {
        int x,y;
    } Snake[10],q1[1000000];//记录贪食蛇的坐标
    int ans=-1;
    struct snakeState
    {
        snake body[8];
        int num;
    } q[1000000];//一整条蛇和蛇走的路程
    bool Map[21][21];
    bool visit[21][21][17000];
    int movex[4]= {0,1,0,-1}; //l,d,r,u
    int movey[4]= {-1,0,1,0};
    bool visit1[21][21];
    int move[21][21];
    int inmap(snake &x,snake body[])//判断是否可以走这步
    {
        if(x.x<=0||x.y<=0||x.x>n||x.y>m||Map[x.x][x.y])
            return 0;
        for(int i=1; i<k; i++)//蛇头与蛇身相撞,则不可以走
            if(x.x==body.x&&x.y==body.y)
                return 0;
        for(int i=k-1; i>0; i--)//如果可以走这步将贪食蛇的位置更新
            body=body[i-1];
        body[0].x=x.x;//贪食蛇蛇头的新坐标
        body[0].y=x.y;
        return 1;//返回成功
    }
    int findmove(snake &a,snake &b)//找出从位置b-a是哪个方向过来的
    {
        if(a.x==b.x)
        {
            if(a.y<b.y)
                return 0;//返回值与movex,movey的值要匹配
            else return 1;
        }
        else
        {
            if(a.x>b.x)
                return 3;
            else return 2;
        }
    }
    void bfs()
    {
        int i,j;
        snakeState a;
        for(i=0; i<k; i++)
            a.body=Snake;
        int num=0,cnt=0;
        a.num=0;
        int state=0;
        for(i=0; i<k-1; i++)
            state=4*state+findmove(Snake,Snake[i+1]);//计算贪食蛇的状态(唯一性)根据前一状态走到后一状态的方向计算得出
        visit[Snake[0].x][Snake[0].y][state]=1;
        q[0]=a;
        num++;
        while(cnt<num)
        {
            snakeState temp=q[cnt];
            cnt++;
            if(temp.body[0].x==1&&temp.body[0].y==1)
            {
                ans=temp.num;
                return ;
            }
            for(i=0; i<4; i++)
            {
                snakeState now=temp;
                snake now1;
                now1.x=temp.body[0].x+movex;
                now1.y=temp.body[0].y+movey;
                if(!inmap(now1,now.body))//是否可以走
                    continue;
                now.num=temp.num+1;
                state=0;
                for(j=0; j<k-1; j++)
                    state=4*state+findmove(now.body[j],now.body[j+1]);//计算当前的状态
                if(visit[now.body[0].x][now.body[0].y][state])
                    continue;
                visit[now.body[0].x][now.body[0].y][state]=1;
                if(now.body[0].x==1&&now.body[0].y==1)
                {
                    ans=now.num;
                    return ;
                }
                q[num]=now;
                num++;
            }
        }
    }
    void bfs1()//计算min和max
    {
        int num=0,cnt=0;
        q1[num]=Snake[0];
        num++;
        visit1[Snake[0].x][Snake[0].y]=1;
        move[Snake[0].x][Snake[0].y]=1;
        while(cnt<num)
        {
            snake temp=q1[cnt];
            cnt++;
            if(temp.x==1&&temp.y==1)
            {
                return ;
            }
            for(int i=0; i<4; i++)
            {
                int tx=temp.x+movex;
                int ty=temp.y+movey;
                if(tx>=1&&ty>=1&&tx<=n&&ty<=m&&!visit1[tx][ty])
                {
                    move[tx][ty]=move[temp.x][temp.y]+1;
                    if(tx==1&&ty==1)
                        return ;
                    visit1[tx][ty]=1;
                    snake now;
                    now.x=tx;
                    now.y=ty;
                    q1[num]=now;
                    num++;
                }
            }
        }
    }
    void show()
    {
        int i,j;
        for(i=1; i<=n; i++)
        {
            for(j=1; j<=m; j++)
                cout<<move[j]<<" ";
            cout<<endl;
        }

    }
    int main()
    {
        int i,j,l,CASE=0;
        while(scanf("%d%d%d",&n,&m,&k),n|m|k)
        {
            memset(Map,0,sizeof(Map));
            memset(visit,0,sizeof(visit));
            memset(visit1,0,sizeof(visit1));
            memset(move,0,sizeof(move));
            for(i=0; i<k; i++)
            {
                scanf("%d%d",&Snake.x,&Snake.y);
            }
            int kkk,x,y;
            ans=-1;
            //show();
            scanf("%d",&kkk);
            while(kkk--)
            {
                scanf("%d%d",&x,&y);
                Map[x][y]=1;
                visit1[x][y]=1;
            }
            bfs1();//第一次BFS只考虑蛇头和stone;
            //show();
            if(move[1][1]==0)//如果(1,1)不可到达
            {
                printf("Case %d: -1\n",++CASE);
                continue;
            }
            int min=move[1][1];
            memset(move,0,sizeof(move));
            for(i=1; i<=n; i++)
            {
                for(j=1; j<=m; j++)
                    visit1[j]=Map[j];
            }
            for(i=1; i<k; i++)//第二次BFS,还要另外将蛇身看成stone
                visit1[Snake.x][Snake.y]=1;
            bfs1();
            int max=move[1][1];
            if(min==max)//如果 min和max相等
            {
                printf("Case %d: %d\n",++CASE,min-1);
                continue;
            }
            bfs();
            printf("Case %d: %d\n",++CASE,ans);
        }
        return 0;
    } 
  • 相关阅读:
    异常处理
    PAT——1048. 数字加密
    PAT——1047. 编程团体赛
    PAT——1046. 划拳
    PAT——1045. 快速排序(25)
    PAT——1044. 火星数字
    PAT——1043. 输出PATest
    PAT——1042. 字符统计
    PAT——1041. 考试座位号
    PAT——1040. 有几个PAT
  • 原文地址:https://www.cnblogs.com/CKboss/p/3351095.html
Copyright © 2020-2023  润新知