• POJ 1324 Holedox Moving 搜索


    题目地址: http://poj.org/problem?id=1324


    优先队列---A*的估价函数不能为蛇头到(1,1)的距离,这样会出错。

    看了discuss,有大神说这题A*的估价函数为BFS (0,0)到各点的花费在乘上10 ,但是还是不清楚,希望知道的可以给我留个言,谢谢了。


    思路:

    用0,1,2,3表示方向,这样就可以用四进制状态压缩了。

    总共需要3+3*4^1+……3*4^6.

    推荐大家能不用STL就不用STL,太浪费时间了。

    下面是用STL超时代码和用数组模拟AC代码。


    超时代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <list>
    #include <deque>
    #include <queue>
    #include <iterator>
    #include <stack>
    #include <map>
    #include <set>
    #include <algorithm>
    #include <cctype>
    using namespace std;
    
    typedef long long LL;
    const int N=21;
    const LL II=1000000007;
    
    int n,m,L;
    int maps[N][N];//0代表空,1代表蛇身体,2代表石头
    bool vis[N][N][17000];//状态压缩
    int t[4][2]={0,-1,1,0,0,1,-1,0};
    
    struct xh
    {
        int step;
        int po[11][2];
    }w,e;
    
    int location(int px,int py,int nx,int ny)//求两个节点的相对位置
    {
        if(px==nx)
        {
            if(py>ny)
                return 0;
            else
                return 1;
        }
        else
        {
            if(px>nx)
                return 2;
            else
                return 3;
        }
    }
    
    int gethash(int B[][2])
    {//得到状态
        int s=0;
        for(int i=0;i<L-1;i++)
            s=s*4+location(B[i][0],B[i][1],B[i+1][0],B[i+1][1]);
        return s;
    }
    
    bool inmap(int x,int y,xh a)
    {
        if(!(x>=1&&x<=n&&y>=1&&y<=m))
            return false;
        if(maps[x][y]==2)
            return false;
        for(int i=0;i<L;i++)//蛇头和蛇尾相连也不行的
            if(x==a.po[i][0]&&y==a.po[i][1])//判断是否这一步为蛇身
                return false;
        return true;
    }
    
    void bfs()
    {
        int i,j,hash,x,y;
        w.step=0;
        hash=gethash(w.po);
        x=w.po[0][0];    y=w.po[0][1];
        vis[x][y][hash]=true;
        queue<xh> q;
        q.push(w);
        if(x==1&&y==1)
        {
            printf("0
    ");
            return ;
        }
        while(!q.empty())
        {
            e=q.front();
            q.pop();
            for(i=0;i<4;i++)
            {
                w=e;
                x=w.po[0][0];    y=w.po[0][1];
                x+=t[i][0];     y+=t[i][1];
                if(!inmap(x,y,w)) continue;
                for(j=L-1;j>=1;j--)
                {
                    w.po[j][0]=w.po[j-1][0];
                    w.po[j][1]=w.po[j-1][1];
                }
                w.po[0][0]=x;    w.po[0][1]=y;
                hash=gethash(w.po);
                if(vis[x][y][hash]) continue;
                vis[x][y][hash]=true;
                w.step++;
                q.push(w);
                if(x==1&&y==1)
                {
                    printf("%d
    ",w.step);
                    return ;
                }
            }
        }
        printf("-1
    ");
    }
    
    int main()
    {
        int i,k,ci=0;
        while(scanf("%d%d%d",&n,&m,&L)&&(n+m+L))
        {
            memset(maps,0,sizeof(maps));
            memset(vis,false,sizeof(vis));
            for(i=0;i<L;i++)
            {
                scanf("%d%d",&w.po[i][0],&w.po[i][1]);
            }
            scanf("%d",&k);
            while(k--)
            {
                int a,b;
                scanf("%d%d",&a,&b);
                maps[a][b]=2;//石头
            }
            printf("Case %d: ",++ci);
            bfs();
        }
        return 0;
    }
    


    用STL写就超时了,用数组模拟就过了

    AC代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <list>
    #include <deque>
    #include <queue>
    #include <iterator>
    #include <stack>
    #include <map>
    #include <set>
    #include <algorithm>
    #include <cctype>
    using namespace std;
    
    typedef long long LL;
    const int N=21;
    const LL II=1000000007;
    
    int n,m,L;
    int maps[N][N];//0代表空,1代表蛇身体,2代表石头
    bool vis[N][N][17000];//状态压缩
    int t[4][2]={0,-1,1,0,0,1,-1,0};
    
    struct xh
    {
        int step;
        int po[11][2];
    }w,e,q[5000004];
    
    int location(int px,int py,int nx,int ny)//求两个节点的相对位置
    {
        if(px==nx)
        {
            if(py>ny)
                return 0;
            else
                return 1;
        }
        else
        {
            if(px>nx)
                return 2;
            else
                return 3;
        }
    }
    
    int gethash(int B[][2])
    {//得到状态
        int s=0;
        for(int i=0;i<L-1;i++)
            s=s*4+location(B[i][0],B[i][1],B[i+1][0],B[i+1][1]);
        return s;
    }
    
    bool inmap(int x,int y,xh a)
    {
        if(!(x>=1&&x<=n&&y>=1&&y<=m))
            return false;
        if(maps[x][y]==2)
            return false;
        for(int i=0;i<L;i++)//蛇头和蛇尾相连也不行的
            if(x==a.po[i][0]&&y==a.po[i][1])//判断是否这一步为蛇身
                return false;
        return true;
    }
    
    void bfs()
    {
        int i,j,hash,x,y,head=0,tail=0;
        w.step=0;
        hash=gethash(w.po);
        x=w.po[0][0];    y=w.po[0][1];
        vis[x][y][hash]=true;
        q[tail++]=w;
        if(x==1&&y==1)
        {
            printf("0
    ");
            return ;
        }
        while(head<tail)
        {
            e=q[head++];
            for(i=0;i<4;i++)
            {
                w=e;
                x=w.po[0][0];    y=w.po[0][1];
                x+=t[i][0];     y+=t[i][1];
                if(!inmap(x,y,w)) continue;
                for(j=L-1;j>=1;j--)
                {
                    w.po[j][0]=w.po[j-1][0];
                    w.po[j][1]=w.po[j-1][1];
                }
                w.po[0][0]=x;    w.po[0][1]=y;
                hash=gethash(w.po);
                if(vis[x][y][hash]) continue;
                vis[x][y][hash]=true;
                w.step++;
                q[tail++]=w;
                if(x==1&&y==1)
                {
                    printf("%d
    ",w.step);
                    return ;
                }
            }
        }
        printf("-1
    ");
    }
    
    int main()
    {
        int i,k,ci=0;
        while(scanf("%d%d%d",&n,&m,&L)&&(n+m+L))
        {
            memset(maps,0,sizeof(maps));
            memset(vis,false,sizeof(vis));
            for(i=0;i<L;i++)
            {
                scanf("%d%d",&w.po[i][0],&w.po[i][1]);
            }
            scanf("%d",&k);
            while(k--)
            {
                int a,b;
                scanf("%d%d",&a,&b);
                maps[a][b]=2;//石头
            }
            printf("Case %d: ",++ci);
            bfs();
        }
        return 0;
    }
    


  • 相关阅读:
    临时表 Vs 表变量
    發行項帶篩選的合併複製問題之訂閱者更新導致部份數據丟失
    生成创建表的脚本V2.0(PowerShell版)
    PowerShell应用之事务复制
    PowerShell应用之批量还原数据库(支持完整,差异,事务日志)
    一个有意思的问题:如何根据一年中的第几周,查询出它周六和周日对应的日期
    千万级数据的分页
    了解SQL Server触发器及触发器中的事务
    修改表主键字段数据类型(up_ModifyPrimaryColumn)
    The specified CGI application encountered an error and the server terminated the processThe specified CGI application encountered an error and the server terminated the process
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3174571.html
Copyright © 2020-2023  润新知