康托展開:
公式:x=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[2]*1!+a[1]*0!;
利用這個公式,我們可以求出在一列數中,已知的這一列數是這列數的全排列的字典序中的的幾個。我們可以應用康拓展開來求出一列數的全排列,也可以用康托展開進行判重。
int kt(int n,int s)
擴充套件乙個反向的節點
if(達到狀態)
}這種搜尋方法是有問題的,當我們在逐個擴充套件時,可能會等不到這一層的最優解被擴充套件出就停止搜尋了
s-t的最短路,交替節點搜尋(一次正向節點,一次反向節點)時
step 1 : s –> 1 , 2
step 2 : t –> 3 , 4
step 3 : 1 –> 5
step 4 : 3 –> 5
返回最短路為
4,錯誤的,事實是3,
s-2-4-t
所以當我們在進行搜尋時,應該把正向或反向的佇列的這一步中的狀態全部擴充套件完以後,再去擴充套件另乙個方向中的佇列,這樣我們就可以保證不會出現最優的情況還沒有被搜尋出來的時候就已經break掉了。
例題: codevs
1225 八數碼難題
題目描述
description
yours和zero在研究a*啟發式演算法.拿到一道經典的a*問題,但是他們不會做,請你幫他們.
問題描述
在3×3的棋盤上,擺有八個棋子,每個棋子上標有1至8的某一數字。棋盤中留有乙個空格,空格用0來表示。空格周圍的棋子可以移到空格中。要求解的問題是:給出一種初始布局(初始狀態)和目標布局(為了使題目簡單,設目標狀態為123804765),找到一種最少步驟的移動方法,實現從初始布局到目標布局的轉變。
輸入描述 input description
輸入初試狀態,一行九個數字,空格用0表示
輸出描述 output description
只有一行,該行只有乙個數字,表示從初始狀態到目標狀態需要的最少移動次數(測試資料中無特殊無法到達目標狀態資料)
樣例輸入 sample input
283104765
樣例輸出 sample output 4
題解: 在這個題中,我們已知起始狀態和目標狀態,此時就可以利用雙向廣搜去解決,但在搜尋的過程中還有乙個小問題,就是判重的問題,因為這是3*3的方格,所以如果我們把每乙個格用一位數字儲存的話,布林陣列就會開到9位,記憶體是不允許的,所以這個時候我們可以選擇用康托展開判重,這樣空間複雜度就變成了9!,就可以實現了
#include#include#includeusing namespace std;
struct point
l[1000000][3];
int fac[10]=;
int c[1000000][3]=,h1,h2,t1,t2,xi[4]=,yi[4]=,en[9]=;
char a[10];
bool f[500000][3],ff=false;
int kt(int s)
break;}}
}} if(ff) break;
h1+=1;
for(i=0;i<4;++i)
break;}}
}} if(ff) break;
h2+=1;
}}
借助八數碼問題,雙向廣搜,康托展開,逆序數奇偶性
1.首先判斷是否有解 核心思想是根據一維狀態的逆序數奇偶性來判斷 將它表徵為一維狀態 0 1 2 3 4 5 6 7 8 它的逆序數為0,偶數。考慮數字的移動,左移or右移均不改變其一維狀態,因此逆序數的奇偶性不變。上移or下移時,一維狀態中某一位的數字往前或者往後跳了兩格 2 相應的,逆序數 2,...
康托展開 康托逆展開
x a n n 1 a n 1 n 2 a i i 1 a 1 0 其中a i 為當前未出現的元素中是排在第幾個 從0開始 這就是康托展開。康托展開可用 實現。編輯 把乙個整數x展開成如下形式 x a n n 1 a n 1 n 2 a i i 1 a 2 1 a 1 0 其中a i 為當前未出現的...
康托展開 逆康托展開
康托展開 問題 給定的全排列,計算出它是第幾個排列 求序列號 方法 康托展開 對於乙個長度為 n 的排列 num 1 n 其序列號 x 為 x a 1 n i a 2 n 2 a i n i a n 1 1 a n 0 其中a i 表示在num i 1 n 中比num i 小的數的數量 includ...