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\n");

        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\n",w.step);

                return ;

            }

        }

    }

    printf("-1\n");

}



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\n");

        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\n",w.step);

                return ;

            }

        }

    }

    printf("-1\n");

}



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;

}


 

 

 

你可能感兴趣的:(poj)