關於康托的講解:
康托展開
康托展開的公式
把乙個整數x展開成如下形式:
x=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[2]*1!+a[1]*0!
其中,a為整數,並且0<=a[i]康托展開的應用例項
表示1,2,3,...,n的排列如 按從小到大排列一共6個。123 132 213 231 312 321 。
代表的數字 1 2 3 4 5 6 也就是把10進製數與乙個排列對應起來。
他們間的對應關係可由康托展開來找到。
如我想知道321是中第幾個大的數可以這樣考慮 :
第一位是3,當第一位的數小於3時,那排列數小於321 如 123、 213 ,小於3的數有1、2 。所以有2*2!個。再看小於第二位2的:小於2的數只有乙個就是1 ,所以有1*1!=1 所以小於321的排列數有2*2!+1*1!=5個。所以321是第6個大的數。 2*2!+1*1!是康托展開。
再舉個例子:1324是排列數中第幾個大的數:第一位是1小於1的數沒有,是0個 0*3! 第二位是3小於3的數有1和2,但1已經在第一位了,所以只有乙個數2 1*2! 。第三位是2小於2的數是1,但1在第一位,所以有0個數 0*1! ,所以比1324小的排列有0*3!+1*2!+0*1!=2個,1324是第三個大數。
康托展開的**實現
後文的pascal程式經檢驗可以正確工作,並指示出了乙個簡潔的計算方法,和前文的運算思路略有不同,不需要檢驗某數碼是否使用過,只需檢查第(n+1-i)位之後比第(n+1-i)位小的位的數量,將這個數量作為公式中的a[i]。(1<=i<=n)
並附此演算法c++版本。
康托展開的**(c++語言):
unsigned long cantor(unsigned long s)
long x=0,i,p,k,j;
bool hash[8]=;
for (i=8;i>=2;i--)
k=s>> 3*(i-1);
s-=k<<3*(i-1);
hash[k]=true;
p=k;
for (j=0;j<=k-1;j++)
if (hash[j])
p--;
x+=fac[i-1]*p;
return x;
康托展開的**(pascal語言):
s為陣列,用來儲存要求的數,形如(1,3,2,4)。
n為陣列中元素個數。
fac[x]為x!
*function cantor:longint:;
*var
* i,j,temp:integer;
* num:longint;
*begin
* num:=0;
* for i:=1 to n-1 do
* begin
* temp:=0;
* for j:=i+1 to n do
* if s[j]* num:=num+fac[n-i]*temp;
* end;
*cantor:=num+1;
*end;
康托展開的**(c語言):
//引數int s為待展開之數的各位數字,如需展開2134,則s[4]=.
int fac=;//...
long cantor(int s,int n){
int i,j,temp,num;
num=0;
for(i=1;itemp=0;
for(int j=i+1;j<=n;j++){
if(s[j]num+=fac[n-i]*temp;
return (num+1);
特長生模擬 八數碼(bfs hash)
問題描述 有3 3共9個格仔,其中有乙個格仔是空的,其他格仔填滿了1 8之間不同的數字。通過移動格仔可以改變量字和空格的位置,現在給你初狀態和末狀態,請你給出最少的步數。問題輸入 給出6行,每行有三個數,每兩個數用乙個空格空開,每個數在0 8之間,其中0表示空格。前三行表示初始狀態,後三行表示目標狀...
借助八數碼問題,雙向廣搜,康托展開,逆序數奇偶性
1.首先判斷是否有解 核心思想是根據一維狀態的逆序數奇偶性來判斷 將它表徵為一維狀態 0 1 2 3 4 5 6 7 8 它的逆序數為0,偶數。考慮數字的移動,左移or右移均不改變其一維狀態,因此逆序數的奇偶性不變。上移or下移時,一維狀態中某一位的數字往前或者往後跳了兩格 2 相應的,逆序數 2,...
八數碼問題 九宮格重排 利用康托展開 判重
問題 e 藍橋杯 歷屆試題 九宮重排 時間限制 1sec 記憶體限制 128mb 提交 69 解決 17 題目描述 如下面第乙個圖的九宮格中,放著 1 8 的數字卡片,還有乙個格仔空著。與空格子相鄰的格仔中的卡片可以移動到空格中。經過若干次移動,可以形成第二個圖所示的局面。我們把第乙個圖的局面記為 ...