[LUOGU2730] 魔板

搜索水题。因为只有8个数,排列一共有40320种,直接bfs,判重就行了。

但是判重的时候直接用8进制表示的话要88的bool数组。这种操作太low了,于是我们可以用康托展开,降成8!。

康托展开其实就是一个简单的公式,很好意会。。。。

#include <iostream>
#include <cstdlib>
#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
const int fac[]={0,1,2,6,24,120,720,5040,40320,362880};
int rnk;
bool vis[50005];
struct Node{
    int a[9],step,pre;
    char c;
}a,q[50005];
int cantor(Node b) {
    int ans=0;
    for(int i=1;i<=8;i++) {
        int cnt=0;
        for(int j=i+1;j<=8;j++) {
            if(b.a[j]<b.a[i]) cnt++;
        }
        ans+=(cnt*fac[8-i]);
    }
    return ans;
}
Node A(Node x) {
    for(int i=1;i<=4;i++) swap(x.a[i],x.a[9-i]);
    return x;
}
Node B(Node x) {
    swap(x.a[1],x.a[4]),swap(x.a[8],x.a[5]);
    swap(x.a[2],x.a[4]),swap(x.a[7],x.a[5]);
    swap(x.a[3],x.a[4]),swap(x.a[5],x.a[6]);
    return x;
}
Node C(Node x) {
    swap(x.a[3],x.a[2]),swap(x.a[7],x.a[6]),swap(x.a[2],x.a[6]);
    return x;
}
int h,t;
void print(Node x) {
    if(!x.pre) return;
    print(q[x.pre]);    printf("%c",x.c);

}
void bfs() {
    h++,t++;
    for(int i=0;i<9;i++)q[1].a[i]=i;
    while(h<=t) {
        bool flag=1;
        for(int i=1;i<=8;i++) if(q[h].a[i]!=a.a[i]) {flag=0;break;}
        if(flag) {printf("%d
",q[h].step),print(q[h]);exit(0);}
        Node tp;int kt;
        tp=A(q[h]);kt=cantor(tp);
        if(!vis[kt]){vis[kt]=1;q[++t]=tp;q[t].step++,q[t].pre=h;q[t].c='A';}
        tp=B(q[h]);kt=cantor(tp);
        if(!vis[kt]){vis[kt]=1;q[++t]=tp;q[t].step++;q[t].pre=h;q[t].c='B';}
        tp=C(q[h]);kt=cantor(tp);
        if(!vis[kt]){vis[kt]=1;q[++t]=tp;q[t].step++;q[t].pre=h;q[t].c='C';}
        h++;
    }
}
int main() {
    for(int i=1;i<=8;i++) scanf("%d",&a.a[i]);
    bfs();
}
Magic Squares

 

我是咸鱼。转载博客请征得博主同意Orz
原文地址:https://www.cnblogs.com/sdfzhsz/p/9657444.html