一个康托展开的板子

Posted Achen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一个康托展开的板子相关的知识,希望对你有一定的参考价值。

八数码问题传送门

技术分享图片
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<vector>
#include<queue>
#include<ctime>
#include<cmath>
const int N=107;
typedef long long LL;
using namespace std;

template<typename T> void read(T &x) {
    char ch=getchar(); x=0; T f=1;
    while(ch!=-&&(ch<0||ch>9)) ch=getchar();
    if(ch==-) f=-1,ch=getchar();
    for(;ch>=0&&ch<=9;ch=getchar()) x=x*10+ch-0; x*=f;
}

int fac[N];
int kt(int n,int a[]) {
    int k=0;
    for(int i=1;i<=n;i++) {
        int t=0;
        for(int j=i+1;j<=n;j++)
            if(a[j]<a[i]) t++;
        k+=t*fac[n-i];
    }
    return k+1;
}

int vis[N];
void rkt(int n,int k,int a[]) {
    memset(vis,0,sizeof(vis));
    k--;
    for(int i=1;i<=n;i++) {
        int t=k/fac[n-i],j;
        for(j=1;j<=n;j++) if(!vis[j]) {
            if(!t) break;
            t--;    
        }
        a[i]=j; vis[j]=1;
        k=k%fac[n-i];
    }
}

int main() {
#ifdef DEBUG
    freopen(".in","r",stdin);
    freopen(".out","w",stdout);
#endif
    return 0;
}
板子
技术分享图片
//Twenty
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#define INF 0xfffffff
using namespace std;
typedef long long LL;
const int maxn=362880+5;
int T,a[10],b[10],p[10],f[maxn],d[maxn],g[maxn];
 
void read(int &ret) {
    int f=1; ret=0; char ch=getchar();
    while(ch!=-&&(ch<0||ch>9)) ch=getchar();
    if(ch==-) f=-1,ch=getchar();
    for(;ch>=0&&ch<=9;ch=getchar()) ret=ret*10+ch-0; ret*=f;
}
 
struct node {
    int x;
    node(int x):x(x){}
    friend bool operator <(const node &A,const node &B) {
        return  d[A.x]+g[A.x]>d[B.x]+g[B.x];
    }
};
 
priority_queue<node>que;

int get_rk(int a[]) {
    int k=0;
    for(int i=1;i<=9;i++) {
        int t=0;
        for(int j=i+1;j<=9;j++)
            if(a[j]<a[i]) t++;
        k+=t*p[9-i];
    }
    return k+1;
}

int vis[10];
void get_b(int k) {
    memset(vis,0,sizeof(vis));
    k--;
    for(int i=1;i<=9;i++) {
        int t=k/p[9-i],j;
        for(j=1;j<=9;j++) if(!vis[j]) {
            if(!t) break;
            t--;    
        }
        b[i]=j; vis[j]=1;
        k=k%p[9-i];
    }
}
 
void cal(int x){
    if(g[x]!=-1) return;
    g[x]=0;
    for(int i=1;i<10;i++) {
        int tp=b[i];
        int xx=(b[i]-1)/3,yy=b[i]-xx*3;xx++;
        int o=(i-1)/3,p=i-o*3;
        g[x]+=abs(xx-o-1)+abs(yy-p);
    }
    return;
}
 
void push(int *q,int pr) {
    int x=get_rk(q);
    if(d[pr]+1>=d[x]) return;
    d[x]=min(d[x],d[pr]+1);
    //if(g[x]!=-1) return;
    cal(x); 
    que.push(node(x));
}
 
int op(int x,int y) {
    return (x-1)*3+y;
}
 
void smg(int tpp,int tp,int pr) {
    swap(b[tpp],b[tp]);
    push(b,pr);
    swap(b[tpp],b[tp]);
}
 
void work() {
    int x=get_rk(a);
    cal(x);  d[x]=0;
    while(!que.empty()) que.pop();
    que.push(node(x));
    int tp;
    while(!que.empty()) {
        node now=que.top();
        que.pop();
        if(now.x==1) break;
        get_b(now.x);
        for(int i=1;i<10;i++) if(b[i]==9) {
            tp=i; break;
        }
        int xx=(tp-1)/3,yy=tp-xx*3; xx++;
        if(xx>1) {
            int tpp=op(xx-1,yy);
            smg(tpp,tp,now.x);
        }
        if(xx<3) {
            int tpp=op(xx+1,yy);
            smg(tpp,tp,now.x);
        }
        if(yy>1) {
            int tpp=op(xx,yy-1);
            smg(tpp,tp,now.x);         
        }
        if(yy<3) {
            int tpp=op(xx,yy+1);
            smg(tpp,tp,now.x);
        }
    }
}
 
void init() {
    read(T);
    p[0]=1; p[1]=1;
    for(int i=2;i<10;i++) p[i]=p[i-1]*i;
    while(T--) {
        memset(g,-1,sizeof(g));
        for(int i=1;i<maxn;i++) d[i]=INF;
        for(int i=1;i<10;i++) {
            read(a[i]);
            if(a[i]==0) a[i]=9;
        }
        work();
        if(d[1]!=INF) printf("%d\n",d[1]);
        else printf("No Solution!\n");
    }
}
 
int main()
{
    init();
    return 0;
}
八数码问题

 

以上是关于一个康托展开的板子的主要内容,如果未能解决你的问题,请参考以下文章

宽搜经典题之二——8数码难题+康托展开

康托展开 / 逆康托展开

康托展开 & 逆康托展开

全排列的编码与解码——康托展开 (附完整代码)

数据结构——康托展开与逆康托展开

康托展开与康托展开的逆运算