uva1601双向bfs和数组对应

try1:局限于原来的bfs思路,先把第一个ghost走了,再走第2个,但是如果这样走,这是定好了先后顺序的走,(因为1个走了,这个位置的状态会影响下一个走)因此这样想,3个鬼的先后顺序有6种,总共每一步就得555*6.

try2:百度别人的博客,得到try1的解决方案,用排列组合的方式,如果有一个位置同时有2个鬼,再把这个除去,也就是用循环得到每一次走的情况,而不是try1中的递归。
同时看到了双bfs的思路,自己尝试写,但是错了,看到https://blog.csdn.net/crazysillynerd/article/details/42681579这个博客,才知道双向bfs要注意什么。
提交tle,原因是自己对于每个位置与相邻位置的关系处理是用map<int,map<int,vectore > >,明显这得比用数组 int[a][b]=cnt,int x[cnt]= y[cnt]=…要慢很多,因为在map中查找要一段时间,而用数组直接对照。

try3:网上得知是tle的原因后,用数组标记换map,用空间换时间,同时草草看网上代码,得到一个灵感,可以把3个坐标压缩成一个数字,因为3个坐标有6个数字,每个数字小于16,因此32位可以保存这些数字。
但是写了始终都是wa,第一个样例居然得不出答案的原因是自己脑抽了,在n=2时,补充n=3这个位置的数时from和to上要相等,因为用了双bfs。对于第二个样例居然用6步就可以走完,百思不得其解自己的代码是如何走的,正确是要36步。
实在不行了,就去抄了别人的代码一遍,把别人代码里不懂的东西弄懂后,就明白第二个样例为什么是那样了,因为2个ghost就算不在一个位置,他们也可能是违规交换的,而使用的是单纯排列组合,没有把这个情况去掉。把自己原来的那个代码在这个地方加判断了一下,就过了。

感谢这个代码,很简洁,学到了很多东西,https://blog.csdn.net/now_ing/article/details/70169270

try4:自己的代码虽然过了,但是看了如上博客后,自己的代码着实太长了,又优化。

总结:这题学到了啥

A.对于每个坐标,可以用点去表示它,如此变成点集,也就是x=1,y=2的坐标它就是点2;在x[cnt],y[cnt]中可以重新找回点的具体定义,如此好处,点与点方便比较存储。

B.0xff的解压

inline int compress(int a,int b,int c)  {return a<<16|b<<8|c;}//这是压缩,使用了内敛函数
 int a1=(now>>16)&0xff,a2=(now>>8)&0xff,a3=now&0xff;   //这是解压,很巧妙

C.双bfs的注意
要一层层搜,如此才能双向搜到同一层。

D.map的使用很多时候可以用数组来代替,用空间换时间,理清楚后,不麻烦。

E.原来数组中的数字0和’\0’是同一个,所以在使用 for(int k=0;posistep[a1][k]!=’\0’;k++)时要小心了,这同时也是计算数组长度的好方法。

ac代码

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
const int maxn=17*17;
int n;
int id[17][17],posistep[maxn][6],step[2][maxn][maxn][maxn];
inline int compress(int a,int b,int c)  {return a<<16|b<<8|c;}
inline int fobbid  (int p1,int p11,int p2,int p22){return p1==p11||(p1==p22&&p2==p11); }
queue<int>fr,to;
int bfs()
{
    while(!fr.empty()||!to.empty())
    {
        int nu1=fr.size(),nu2=to.size();
        while(nu1--)
        {
            int now=fr.front();
            fr.pop();
            int a1=(now>>16)&0xff,a2=(now>>8)&0xff,a3=now&0xff;
            for(int k=0;posistep[a1][k]!='\0';k++)
            {
                for(int d=0;posistep[a2][d]!='\0';d++)
                { int b1=posistep[a1][k],b2=posistep[a2][d];
                   if(fobbid(b1,b2,a1,a2))continue;
                    for(int f=0;posistep[a3][f]!='\0';f++)
                       {
                           int b3=posistep[a3][f];
                           if(fobbid(b1,b3,a1,a3))continue;
                           if(fobbid(b2,b3,a2,a3))continue;
if(step[1][b1][b2][b3]>0)return (step[1][b1][b2][b3]+step[0][a1][a2][a3]+1);
if(step[0][b1][b2][b3]==-1){step[0][b1][b2][b3]=step[0][a1][a2][a3]+1; fr.push(compress(b1,b2,b3));}
                       }
                }
            }
        }
         while(nu2--)
        {
            int now=to.front();
            to.pop();
            int a1=(now>>16)&0xff,a2=(now>>8)&0xff,a3=now&0xff;
            for(int k=0;posistep[a1][k]!='\0';k++)
            {
                for(int d=0;posistep[a2][d]!='\0';d++)
                { int b1=posistep[a1][k],b2=posistep[a2][d];
                   if(fobbid(b1,b2,a1,a2))continue;
                    for(int f=0;posistep[a3][f]!='\0';f++)
                       {
                           int b3=posistep[a3][f];
                           if(fobbid(b1,b3,a1,a3))continue;
                           if(fobbid(b2,b3,a2,a3))continue;
if(step[0][b1][b2][b3]>0)return (step[0][b1][b2][b3]+step[1][a1][a2][a3]+1);
if(step[1][b1][b2][b3]==-1){step[1][b1][b2][b3]=step[1][a1][a2][a3]+1; to.push(compress(b1,b2,b3));}
                       }
                }
            }
        }
    }
}
int main(void)
{int w,h,cnt;
    while(scanf("%d %d %d",&w,&h,&n)&&w)
    { cnt=0;
    memset(id,0,sizeof(id));
    memset(step,-1,sizeof(step));
    memset(posistep,0,sizeof(posistep));
    while(!fr.empty())fr.pop();
    while(!to.empty())to.pop();
    int from[8],tok[8],i,d,x[maxn],y[maxn];
        getchar();
    for(i=1;i<=h;i++)
     {for(d=1;d<=w;d++)
    {char c=getchar();
    if(c!='#'){id[i][d]=++cnt;x[cnt]=i;y[cnt]=d;}
    if(c>='a'&&c<='u')from[c-'a'+1]=cnt;
    if(c>='A'&&c<='P')tok[c-'A'+1]=cnt;

    }
    getchar();}
    int stx[]={0,-1,0,1,0};int sty[]={0,0,-1,0,1};
    for(i=1;i<=cnt;i++)
    {
        int nx=x[i],ny=y[i];
        int f=0;
        for(int d=0;d<=4;d++)
        {
            int kx=nx+stx[d],ky=ny+sty[d];
            if(id[kx][ky]!=0)posistep[i][f++]=id[kx][ky];
        }
    }
    if(n==1){from[2]=tok[2]=++cnt;posistep[cnt][0]=cnt; from[3]=tok[3]=++cnt;posistep[cnt][0]=cnt;}
    if(n==2){from[3]=tok[3]=++cnt;posistep[cnt][0]=cnt; }
    fr.push(compress(from[1],from[2],from[3]));
    to.push(compress(tok[1],  tok[2],  tok[3]  ));
    step[0][from[1]][from[2]][from[3]]=0;
    step[1][tok[1]][tok[2]][tok[3]]=0;
    cout<<bfs()<<endl;
}
return 0;}

猜你喜欢

转载自blog.csdn.net/qq_43235540/article/details/87337945
今日推荐