POJ - 1077 Eight bfs+康拓展開

題目鏈接

題意:就是一個八數碼問題,求從初始狀態得到解的路徑。

思路:bfs,對於每個狀態通過康拓展開來記錄判重。

康拓展開:設一個狀態a[1...n],其康拓展開X=b[n]*(n-1)!+b[n-1]*(n-2)!+...+b[i]*(i-1)!+....+b[1]*0!;其中b[i]表示在a[i+1]到a[n]中<a[i]的個數。

逆康拓展開:因爲b[i]<i,所以(n-1)!>b[n-1]*(n-2)!+...+b[i]*(i-1)!+....+b[1]*0!,從而根據康拓展開的公式,可得從i=1到i=n,b[i]=num/((i-1)!),num=num%((i-1)!),通過b[i]即可得知a[i]在a序列裏還未出現的數中排第b[i]+1個。

#include<cstdio>
#include<cstring>
#include<string>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<stdlib.h>
using namespace std;
int jc[9]={1,1,2,6,24,120,720,5040,40320};
int change[4]={1,-1,-3,3};//控制方向
bool pd[362881]={};
map < int , int > l;//存路徑
string S;
stack <int> s;
struct node
{
    int a[10];
    int pos;
};
queue <node> q;
int getcontor(int* p)//求康拓展開
{
    int temp;
    int ans=0;
    for(int i=8;i>=1;--i)
    {
        temp=0;
        for(int j=i+1;j<=9;++j)
            if(p[i]>p[j])
                ++temp;
        ans+=(temp*jc[9-i]);
    }
    return ans;
}
inline void Swap(int& x1,int& x2)
{
    int t;
    t=x1;
    x1=x2;
    x2=t;
}
void print(int num)
{
    int b[10]={0,1,2,3,4,5,6,7,8,9};
    int posi=9;
    while(l[num]!=-1)
    {
        s.push(l[num]);
        Swap(b[posi],b[posi-change[l[num]]]);
        posi-=change[l[num]];
        num=getcontor(b);
    }
    int x;
    while(!s.empty())
    {
        x=s.top();
        switch(x)
        {
            case 0:printf("r");break;
            case 1:printf("l");break;
            case 2:printf("u");break;
            case 3:printf("d");break;
            default: break;
        }
        s.pop();
    }
}
int main()
{
    node x,y;
    for(int i=1;i<10;++i)
    {
        cin>>S;
        if(S[0]=='x')
        {
            S[0]='9';
            x.pos=i;
        }
        x.a[i]=(int)(S[0]-'0');
    }
    int num;
    num=getcontor(x.a);
    pd[num]=true;
    l[num]=-1;
    q.push(x);
    bool flag=false;
    while(!q.empty())
    {
        x=q.front();
        q.pop();
        y=x;
        for(int i=0;i<4;++i)
        {
            if(i==0&&(x.pos==3||x.pos==6||x.pos==9))continue ;
            if(i==1&&(x.pos==1||x.pos==4||x.pos==7))continue ;
            y.pos=x.pos+change[i];
            if(y.pos<1||y.pos>9)continue ;
            Swap(y.a[x.pos],y.a[y.pos]);
            num=getcontor(y.a);
            if(!pd[num])
            {
                pd[num]=true;
                l[num]=i;
                q.push(y);
                if(num==0)flag=true;
            }
            Swap(y.a[x.pos],y.a[y.pos]);
        }
        if(flag)break;
    }
    if(pd[0])
        print(0);
    else
        printf("unsolvable\n");
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章