1. 程式人生 > >魔板 Magic Squares

魔板 Magic Squares

根據 calc swa cst pty pop pro void 目標

【題目描述】:
魔板 Magic Squares

【思路】:
是不是感覺和八數碼有點像?
顯而易見的寬搜,把魔板的狀態表示為排列,則狀態最多有\(8! = 40320\)種,空間是可以接受的,對於是第幾個排列可以用康拓展開來實現(我想在做八數碼的時候你們都深知這個套路),然後根據題目中的三種方式轉移狀態,每個狀態轉移出\(3\)個子狀態,註意判重!,一旦目標狀態出現,那個所搜索的層數一定是能得到該狀態的最小步數。最後就是代碼細節多,要仔細。

#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
int calc[]={1,1,2,6,24,120,720,5040};

int mp[3][5];
bool vis[45000];int rest[10];int a[45000][10];int ans;int Ans;int step[45000];int st;
char last[45000];char endd[45000];int fa[45000];

inline bool judge(){//康拓展開標記 
    ans = 0;int id = 7;
    for(int i=1;i<=8;++i) rest[i] = i-1;
    for(int i=1;i<=4;++i){
        ans += (rest[mp[1][i]]) * calc[id];
        for(int j=mp[1][i]+1;j<=8;++j) rest[j]--;
        id--;
    }
    for(int i=1;i<4;++i){
        ans += (rest[mp[2][i]]) * calc[id];
        for(int j=mp[2][i]+1;j<=8;++j) rest[j]--;
        id--;
    }
    ans++;
    if(vis[ans]){
        if(ans == Ans) return 1;
        else return 0;
    }
    vis[ans] = 1;
    id = 0;
    for(int i=1;i<=4;++i) a[ans][++id] = mp[1][i];
    for(int i=1;i<=4;++i) a[ans][++id] = mp[2][i];
    return 1;
}

inline bool A(int x){
    int id = 0;
    for(int i=1;i<=4;++i) mp[1][i] = a[x][++id];
    for(int i=1;i<=4;++i) mp[2][i] = a[x][++id];
    swap(mp[1] , mp[2]);
    return judge();
}

inline bool B(int x){
    int id = 0;
    for(int i=1;i<=4;++i) mp[1][i] = a[x][++id];
    for(int i=1;i<=4;++i) mp[2][i] = a[x][++id];
    swap(mp[1][4] , mp[1][1]);
    swap(mp[2][4] , mp[2][1]);
    for(int i=4;i>=3;--i){
        swap(mp[1][i] , mp[1][i-1]);
        swap(mp[2][i] , mp[2][i-1]);
    }
    return judge();
}

inline bool C(int x){
    int id = 0;
    for(int i=1;i<=4;++i) mp[1][i] = a[x][++id];
    for(int i=1;i<=4;++i) mp[2][i] = a[x][++id];
    swap(mp[1][2] , mp[1][3]);
    swap(mp[1][2] , mp[2][2]);
    swap(mp[2][2] , mp[2][3]);
    return judge();
}

queue<int>q;
inline void bfs(){
    q.push(st);
    while(!q.empty()){
        int u = q.front();q.pop();
        if(A(u)){
            q.push(ans),step[ans] = step[u] + 1;
            last[ans] = 'A';fa[ans] = u;
            if(ans == Ans){printf("%d\n",step[ans]);return ;}
        }
        if(B(u)){
            q.push(ans),step[ans] = step[u] + 1;
            last[ans] = 'B';fa[ans] = u;
            if(ans == Ans){printf("%d\n",step[ans]);return ;}
        }
        if(C(u)){
            q.push(ans),step[ans] = step[u] + 1;
            last[ans] = 'C';fa[ans] = u;
            if(ans == Ans){printf("%d\n",step[ans]);return ;}
        }
    }
}

int main(){
    for(int i=1;i<=4;++i) mp[1][i] = i;
    for(int i=1;i<=4;++i) mp[2][i] = 9 - i;
    judge();st = ans;last[st] = '&';
    for(int i=1;i<=4;++i) a[Ans][i] = i;
    for(int i=5;i<=8;++i) a[Ans][i] = 13-i; 
    for(int i=1;i<=4;++i) scanf("%d",&mp[1][i]);
    for(int i=1;i<=4;++i) scanf("%d",&mp[2][5-i]);
    judge();Ans = ans;
    if(st == Ans){
        puts("0");
        return 0;
    }
    bfs();
    int x = Ans;int num = 0;
    while(last[x] != '&'){
        endd[++num] = last[x];
        x = fa[x];
    }
    for(int i=num;i>=1;--i) printf("%c",endd[i]);
    return 0;
}

魔板 Magic Squares