您的位置:首页 > 其它

八数码第四境界——暴力反向BFS+康托展开判重+打表+回溯记录路径

2017-12-13 22:34 435 查看
(请先看前面3重境界)

由于第三重境界要开一个vector来嵌套许多vector来记录路径,那绝对是开销很大。所以我们采用回溯记录路径。

思路:

原来我们是采用康托展开,比如求出12345678x在全排列的第几个(这里无疑是第一个),用来判断这种状态是否已经到达过了,这里就是vis[1]=1代表已经访问过,vis[1]=0代表未访问过。在每次访问以后都置为1。而现在我们这里不一样了。我们存放的是层数。我们这里想要的是路径吧?所以说这里指的就是在这条路径上的第几个,我们的做法就是在最后找到以后,根据这个第几个,来逐一找到上一个,直到找到终点。以前我们每种状态维护的是一个路径,我们这里只需要维护一个操作就可以了。只要我们能把每种状态的路径,和上一种状态的路径,想办法关联起来,就可以了。

用来找到关联的结构体:

1.  struct res  
2.  {  
3.      int now,fa;  

}res


now存放的就是当前的操作(上下左右),fa就是这条路径上上一个状态的操作在这个res数组中存放的地方。就比如说我现在是这个数组的第10个,我的操作是上,我的fa是7,就代表我上一个操作被存放在了7,我们不断去取即可。所以我们一旦让一个点入栈了,也同时会在这个数组的尾端添加一个。赋予他当前的操作是什么,以及这条路径上上一个操作所存放的位置。这个怎么得知呢?因为我们就是通过上一种状态得出下一种状态的,所以我们只需要在上一种状态得出下一种状态的过程中,把他上一种状态所在这个数组中的位置给他,交给他去维护了。所以我们可以得知,这个res数组,并不是有序的。什么意思呢?并不是说这个状态的操作在这里,下一个状态的操作在这个数组的下一个位置,而是通过fa来进行关联。

上个图:



此外,我们上面讲的康托展开,vis[某个节点对应的康托值] = 这个res集合中的某一位,再以此为依据就能回溯出之前的路径了。

讲了这么多理论,具体看看细化的实现。

1.  if((h.index+1)%3!=0)  
2.          {  
3.              c=h.str[h.index];h.str[h.index]=h.str[h.index+1];h.str[h.index+1]=c;  
4.              h.index++;  
5.              res[cnt].now=4;res[cnt].fa=h.pos;h.pos=cnt;cnt++;  
6.              int t=KT(h.str);  
7.              if(vis[t]==-1)  
8.              {  
9.                  vis[t]=cnt-1;  
10.                 q.push(h);  
11.             }  
12.         }  

if语句判断如果不是在最后一列,那就肯定就可以右移。

下一行,和右边那个数进行交换。

h.index指的是x在状态中的位置

res[cnt].now=4,4指代的是右移操作

res[cnt].fa=h.pos这个指的是你上一个状态所在这个res数组的位置赋给你当前状态去维护

h.pos=cnt这是你当前状态所在这个res数组的位置

cnt++你插入了一个数,自然要++,不然接下来还用不用了

最后如果这个位置没有访问过,那么这个状态在vis中的值,也被置为和你当前h.pos位置一样的值。为什么这里也要作文章,因为最后你输出的时候你肯定要根据所要求的结果在res中定位,那你定位的依据是什么?只能以序列通过求康托值得出在vis中的位置,再去取得这个值。

1.  if(vis[t]!=-1)  
2. 
        {  
3.              t = vis[t];  
4. 
            while(res[t].now!=-1)  
5.              {  
6. 
                if(res[t].now==1)printf("d");  
7.                  if(res[t].now==2)printf("u");  
8. 
                if(res[t].now==3)printf("r");  
9.                  if(res[t].now==4)printf("l");  
10.
                t=res[t].fa;  
11.             }  
12.
        }  
13.         else  
14.
            printf("unsolvable");  

如果vis[t]!=-1,那么就是这种状态肯定是有的,而我们在这个里面存储了他在res中的位置,所以再通过fa一步步回推,得出了序列。

全部代码

#define N 512345  

  

char ss[10];  

struct node  

{  

    char str[10];  

    int pos;  

    int index;  

};  

struct res  

{  

    int now,fa;  

}res
;  

int vis
;  

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

int over,cnt;  

int ans
;  

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 c;  

    queue<node> q;  

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

    over = KT(ss);  

    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.pos=0;g.index=8;  

    int t=KT(g.str);  

    vis[t] = 0;  

    q.push(g);  

    cnt=1;  

    while(!q.empty())  

    {  

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

        int t = KT(g.str);  

        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++;  

            res[cnt].now=4;res[cnt].fa=h.pos;h.pos=cnt;cnt++;  

            int t=KT(h.str);  

            if(vis[t]==-1)  

            {  

                vis[t]=cnt-1;  

                q.push(h);  

            }  

        }  

        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--;  

            res[cnt].now=3;res[cnt].fa=h.pos;h.pos=cnt;cnt++;  

            int t=KT(h.str);  

            if(vis[t]==-1)  

            {  

                vis[t]=cnt-1;  

                q.push(h);  

            }  

        }  

        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;  

            res[cnt].now=2;res[cnt].fa=h.pos;h.pos=cnt;cnt++;  

            int t=KT(h.str);  

            if(vis[t]==-1)  

            {  

                vis[t]=cnt-1;  

                q.push(h);  

            }  

        }  

        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;  

            res[cnt].now=1;res[cnt].fa=h.pos;h.pos=cnt;cnt++;  

            int t=KT(h.str);  

            if(vis[t]==-1)  

            {  

                vis[t]=cnt-1;  

                q.push(h);  

            }  

        }  

    }  

    return false;  

}  

int main()  

{  

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

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

    res[0].now=-1;  

    bfs();  

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

    {  

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

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

        t = KT(ss);  

        if(vis[t]!=-1)  

        {  

            t = vis[t];  

            while(res[t].now!=-1)  

            {  

                if(res[t].now==1)printf("d");  

                if(res[t].now==2)printf("u");  

                if(res[t].now==3)printf("r");  

                if(res[t].now==4)printf("l");  

                t=res[t].fa;  

            }  

        }  

        else  

            printf("unsolvable");  

        printf("\n");  

    }  

    return 0;  

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