標籤:狀態 lib 問題 康托展開 這一 計算 排列 put str
狀態數不是很多,直接 bfs
輸出方案就記錄 pre 狀態即可
但是問題在於存狀態
可行的一些方案是:雜湊/map,康托展開
於是就學了一波康托展開
用康托展開的地方的地方感覺不會很多,畢竟要 n^2 算
大概意思就是給一個排列 hash
計算出來的就是這個排列在所有 n 的排列中的排名
計算方式就從這裡看吧
不過代碼實現略有不同
大體思路是差不多的
逆展開就是當前這一位上的數位排名
從可用數字中選出這個排名的數,並把它從可用集合中刪除
代碼:
#include<algorithm>#include<iostream>#include<cstdlib>#include<cstring>#include<cctype>#include<cstdio>#include<queue>using namespace std;const int MAXN = 11, MAXSIZ = 5;struct INFO{int stt[MAXN], stp, ex;}bgn;int ans, top;int pi[MAXN], out[MAXN], tmp[MAXN];int stp[363000], pre[363000], stk[363000];bool getans, vis[10];queue<INFO> q;inline void turnmid(int *stt) {register int tmp = stt[4];stt[4] = stt[6]; stt[6] = stt[5]; stt[5] = tmp;return;}inline void turnroll(int *stt) {register int tmp = stt[1];stt[1] = stt[4]; stt[4] = stt[7]; stt[7] = stt[8];stt[8] = stt[9]; stt[9] = stt[6]; stt[6] = stt[3];stt[3] = stt[2]; stt[2] = tmp;return;}inline int expnd(int *dst) {register int res = 0, tmp = 0;for(int i = 1; i <= 9; ++i) {tmp = 0;for(int j = i + 1; j <= 9; ++j) tmp += (dst[j] < dst[i]);res += tmp * pi[9 - i];}return res;}inline void antiex(int ex) {register int siz = 8, val = 0;for(int i = 0; i < 9; ++i) tmp[i] = i;for(int i = 1; i <= 9; ++i) {val = (ex / pi[9 - i]);ex %= pi[9 - i];out[i] = tmp[val];for(int j = val; j < siz; ++j) tmp[j] = tmp[j + 1];--siz; }return;}inline void write(int ex) {getans = true;while(~ex) {stk[++top] = ex;//printf("ex = %d\n", ex);ex = pre[ex];}while(top) {antiex(stk[top--]);for(int i = 1; i <= 9; ++i) printf("%d%c", out[i], " \n"[i % 3 == 0]);putchar(‘\n‘);}return;}inline void bfs() {bgn.ex = expnd(bgn.stt);bgn.stp = 0;pre[bgn.ex] = -1;stp[bgn.ex] = 0;q.push(bgn);INFO cur, d1, d2;while(!q.empty()) {cur = q.front(); q.pop();//printf("now state : \n");//for(int i = 1; i <= 9; ++i) //printf("%d%c", cur.stt[i], " \n"[i % 3 == 0]);++cur.stp;d1 = cur;d2 = cur;turnroll(d1.stt);turnmid(d2.stt);d1.ex = expnd(d1.stt);d2.ex = expnd(d2.stt);if(stp[d1.ex] > d1.stp) {stp[d1.ex] = d1.stp;pre[d1.ex] = cur.ex;q.push(d1);}if(stp[d2.ex] > d2.stp) {stp[d2.ex] = d2.stp;pre[d2.ex] = cur.ex;q.push(d2);}if(d1.ex == ans) {printf("%d\n", d1.stp);write(d1.ex);return;}if(d2.ex == ans) {printf("%d\n", d2.stp);write(d2.ex);return;}}return;}int main() {memset(stp, 0x3f, sizeof(stp));pi[0] = pi[1] = 1;for(int i = 0 ;i < 363000; ++i) pre[i] = -1;for(int i = 2; i <= 9; ++i) pi[i] = pi[i - 1] * i;for(int i = 1; i <= 9; ++i) bgn.stt[i] = i - 1;ans = expnd(bgn.stt);for(int i = 1; i <= 9; ++i) scanf("%d", &bgn.stt[i]);bfs();if(!getans) puts("UNSOLVABLE");return 0;}
Luogu2578 [ZJOI2005]九數位遊戲