您的位置:首页 > 其它

八数码第五境界——双向BFS+康托展开判重+回溯记录路径

2017-12-13 23:06 351 查看
(请先看前4大境界)

这里较上一境界,就是把反向的BFS,弄成了双向的BFS。先不说算法的优劣,就光这个双向的BFS,就是指的记录和学习的。

很简单,在结合之前所学的基础上,把单向扩展成双向即可。

结构体

struct node  

{  

    char str[10];  

    int mark,num;  

    int index,hashnum;  

};  

这里的结构体,增加了一个mark,用来判断他是从终点开始bfs的(mark=0)还是从我们所要求的起点开始bfs的(mark=1)。

回溯路径结构体数组,就需要多开一个

struct res  

{  

    int fa,now;  

}res1
,res2
;  

访问与否,也需要多开一个

int vis1
,vis2
;
 

先让终点状态入队列

g.mark=0;g.num=0;g.index=8;  

    vis1[KT(g.str)]=0;  

    q.push(g);

再让起点状态入队列

for(int i=0;i<9;i++)  

        g.str[i]=ss[i];  

    g.mark=1;g.num=0;g.index=temp;  

    vis2[KT(g.str)]=0;  

    q.push(g);  

所以这里我们得知了,我们虽然是bfs,但是仍旧共享一个队列,我们一开始,也是将两个开始状态都入队。

如果找到,应该进行的判断

 
     if(g.mark==0&&vis2[t]!=-1)  

        {  

            ans1=g.num;  

            ans2=vis2[t];  

            return true;  

        }  

        if(g.mark==1&&vis1[t]!=-1)  

        {  

            ans2=g.num;  

            ans1=vis1[t];  

            return true;  

        }  

g.mark==0指代的是从终点开始bfs的,vis2[t]!=-1指代的是这个状态,从起点开始的bfs他走到过。(所以这里用的vis2)

bfs流程

        h=g;  

        if((h.index+1)%3!=0)  

        {  

            c=h.str[h.index];h.str[h.index]=h.str[h.index+1];h.str[h.index+1]=c;  

            h.index++;  

            if(!h.mark){res1[cnt1].now=4;res1[cnt1].fa=h.num;h.num=cnt1;cnt1++;}  

            else {res2[cnt2].now=4;res2[cnt2].fa=h.num;h.num=cnt2;cnt2++;}  

            int t=KT(h.str);  

            if(vis1[t]==-1&&!h.mark)  

            {  

                vis1[t]=h.num;  

                q.push(h);  

                sum1++;  

            }  

            else if(vis2[t]==-1&&h.mark)  

            {  

                vis2[t]=h.num;  

                q.push(h);  

                sum2++;  

            }  

        }  

首先第一个if,意思就是不为第三列,那就是前面两列,所以自然肯定可以右移。

c=h.str[h.index];h.str[h.index]=h.str[h.index+1];h.str[h.index+1]=c; 这个就是右移操作

h.index++; 指代h状态中x所在的位置

接下来的那个if,!h.mark,那意思就是为0的情况,那就是从终点开始的bfs。

if里面的内容就是用来回溯路径的。

else就是代表从起点开始的bfs。

这个时候h较g已经发生了改变,再通过康托展开取得值。

接下来的if。如果这个状态再vis1中未曾出现过且现在是起点开始的bfs,那就把这个状态置为已访问,再把这个新的状态入队列。

最后的sum1++就耐人寻味了。

我们先找到sum所在的地方

声明处

 sum1=sum2=1;  

while(!q.empty())  

    {  

        g=q.front();q.pop();  

        int t = KT(g.str);  

        if(g.mark==0)sum1--;  

        else sum2--;
 

然后在每次入队列的的时候都会减1。所以这个num1就指代了你当前队列中,属于你终点开始的bfs在队列中还剩下几个元素。

最后的终止条件

if(sum1==0||sum2==0)  

            return false;
 

如果其中一个的元素出光了,那就代表返回false,退出了。为什么其中一个元素出光了就代表没机会了呢?难道不能之后从另一个点出发的bfs又走回到你这个路径上来了呢?其实我想说,仅仅这样还限定的不严格。不过我们就先谈谈这个。我们先假设,其中一个bfs所有情况遍历了,另一个bfs在随后走到了这条路上来。那么我想问,这是否意味着另一个bfs总有办法走到之前的bfs的路上来,也就证明他们是相通的。但是第一个bfs走光了,那肯定也代表他把能走相通的路都走过了!所以这是矛盾的。具体什么时候才是真正的没机会了呢?不必深究了。

全部代码

#define N 512345  

  

char ss[10];  

struct node  

{  

    char str[10];  

    int mark,num;  

    int index,hashnum;  

};  

struct res  

{  

    int fa,now;  

}res1
,res2
;  

int vis1
,vis2
;  

int  fac[] = {1,1,2,6,24,120,720,5040,40320};  

int over,ans1,ans2,sum1,sum2,cnt1,cnt2;  

int hehe
;  

int KT(char ss[])  

{  

    int i, j, t, sum;  

    int s[10];  

    for(i=0;i<9;i++)  

    {  

        if(ss[i]=='x')  

            s[i]=0;  

        else  

            s[i]=ss[i]-'0';  

    }  

    sum = 0;  

    for (i=0; i<9; i++)  

    {  

        t = 0;  

        for (j=i+1; j<9; j++)  

            if (s[j] < s[i])  

                t++;  

        sum += t*fac[9-i-1];  

    }  

    return sum+1;  

}  

bool bfs(char ss[], int temp)  

{  

    char c;  

    queue<node> q;  

    while(!q.empty())q.pop();  

  

    node g,h;  

    for(int i=0;i<8;i++)  

        g.str[i]=i+1+'0';  

    g.str[8]='x';g.str[9]='\0';  

    g.mark=0;g.num=0;g.index=8;  

    vis1[KT(g.str)]=0;  

    q.push(g);  

    for(int i=0;i<9;i++)  

        g.str[i]=ss[i];  

    g.mark=1;g.num=0;g.index=temp;  

    vis2[KT(g.str)]=0;  

    q.push(g);  

    sum1=sum2=1;  

    cnt1=cnt2=1;  

  

    while(!q.empty())  

    {  

        g=q.front();q.pop();  

        int t = KT(g.str);  

        if(g.mark==0)sum1--;  

        else sum2--;  

        if(g.mark==0&&vis2[t]!=-1)  

        {  

            ans1=g.num;  

            ans2=vis2[t];  

            return true;  

        }  

        if(g.mark==1&&vis1[t]!=-1)  

        {  

            ans2=g.num;  

            ans1=vis1[t];  

            return true;  

        }  

        h=g;  

        if((h.index+1)%3!=0)  

        {  

            c=h.str[h.index];h.str[h.index]=h.str[h.index+1];h.str[h.index+1]=c;  

            h.index++;  

            if(!h.mark){res1[cnt1].now=4;res1[cnt1].fa=h.num;h.num=cnt1;cnt1++;}  

            else {res2[cnt2].now=4;res2[cnt2].fa=h.num;h.num=cnt2;cnt2++;}  

            int t=KT(h.str);  

            if(vis1[t]==-1&&!h.mark)  

            {  

                vis1[t]=h.num;  

                q.push(h);  

                sum1++;  

            }  

            else if(vis2[t]==-1&&h.mark)  

            {  

                vis2[t]=h.num;  

                q.push(h);  

                sum2++;  

            }  

        }  

        h=g;  

        if(h.index%3!=0)  

        {  

            c=h.str[h.index];h.str[h.index]=h.str[h.index-1];h.str[h.index-1]=c;  

            h.index--;  

            if(!h.mark){res1[cnt1].now=3;res1[cnt1].fa=h.num;h.num=cnt1;cnt1++;}  

            else {res2[cnt2].now=3;res2[cnt2].fa=h.num;h.num=cnt2;cnt2++;}  

            int t=KT(h.str);  

            if(vis1[t]==-1&&!h.mark)  

            {  

                vis1[t]=h.num;  

                q.push(h);  

                sum1++;  

            }  

            else if(vis2[t]==-1&&h.mark)  

            {  

                vis2[t]=h.num;  

                q.push(h);  

                sum2++;  

            }  

        }  

        h=g;  

        if(h.index<6)  

        {  

            c=h.str[h.index];h.str[h.index]=h.str[h.index+3];h.str[h.index+3]=c;  

            h.index+=3;  

            if(!h.mark){res1[cnt1].now=2;res1[cnt1].fa=h.num;h.num=cnt1;cnt1++;}  

            else {res2[cnt2].now=2;res2[cnt2].fa=h.num;h.num=cnt2;cnt2++;}  

            int t=KT(h.str);  

            if(vis1[t]==-1&&!h.mark)  

            {  

                vis1[t]=h.num;  

                q.push(h);  

                sum1++;  

            }  

            else if(vis2[t]==-1&&h.mark)  

            {  

                vis2[t]=h.num;  

                q.push(h);  

                sum2++;  

            }  

        }  

        h=g;  

        if(h.index>2)  

        {  

            c=h.str[h.index];h.str[h.index]=h.str[h.index-3];h.str[h.index-3]=c;  

            h.index-=3;  

            if(!h.mark){res1[cnt1].now=1;res1[cnt1].fa=h.num;h.num=cnt1;cnt1++;}  

            else {res2[cnt2].now=1;res2[cnt2].fa=h.num;h.num=cnt2;cnt2++;}  

            int t=KT(h.str);  

            if(vis1[t]==-1&&!h.mark)  

            {  

                vis1[t]=h.num;  

                q.push(h);  

                sum1++;  

            }  

            else if(vis2[t]==-1&&h.mark)  

            {  

                vis2[t]=h.num;  

                q.push(h);  

                sum2++;  

            }  

        }  

        if(sum1==0||sum2==0)  

            return false;  

    }  

    return false;  

}  

int main()  

{  

    int i,j,k,kk,t,x,y,z;  

    while(scanf("%s",ss)!=EOF)  

    {  

        if(ss[0]=='x')x=0;  

        for(i=1;i<9;i++)  

        {  

            scanf("%s",ss+i);  

            if(ss[i]=='x') x=i;  

        }  

  

        ans1=ans2=-1;  

        memset(vis1,-1,sizeof(vis1));  

        memset(vis2,-1,sizeof(vis2));  

        res1[0].now=res2[0].now=-1;  

  

        if(bfs(ss,x))  

        {  

            x=0;  

            if(res2[ans2].now==-1&&res1[ans1].now==-1)  

            {  

                printf("lr\n");  

                continue;  

            }  

            while(res2[ans2].now!=-1)  

            {  

                hehe[x++]=res2[ans2].now;  

                ans2=res2[ans2].fa;  

            }  

            for(i=x-1;i>=0;i--)  

            {  

                if(hehe[i]==1)printf("u");  

                if(hehe[i]==2)printf("d");  

                if(hehe[i]==3)printf("l");  

                if(hehe[i]==4)printf("r");  

            }  

            while(res1[ans1].now!=-1)  

            {  

                if(res1[ans1].now==1)printf("d");  

                if(res1[ans1].now==2)printf("u");  

                if(res1[ans1].now==3)printf("r");  

                if(res1[ans1].now==4)printf("l");  

                ans1=res1[ans1].fa;  

            }  

        }  

        else  

            printf("unsolvable");  

        printf("\n");  

    }  

    return 0;  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: