日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

【转】康拓展开

發(fā)布時(shí)間:2023/12/10 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【转】康拓展开 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

———本文轉(zhuǎn)自:http://www.cnblogs.com/1-2-3/archive/2011/04/25/generate-permutation-part2.html

1、康托展開(kāi)
  康托展開(kāi)的公式是 X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! 其中,ai為當(dāng)前未出現(xiàn)的元素中是排在第幾個(gè)(從0開(kāi)始)。
  這個(gè)公式可能看著讓人頭大,最好舉個(gè)例子來(lái)說(shuō)明一下。例如,有一個(gè)數(shù)組 s = ["A", "B", "C", "D"],它的一個(gè)排列 s1 = ["D", "B", "A", "C"],現(xiàn)在要把 s1 映射成 X。n 指的是數(shù)組的長(zhǎng)度,也就是4,所以
X(s1) = a4*3! + a3*2! + a2*1! + a1*0!
關(guān)鍵問(wèn)題是 a4、a3、a2 和 a1?等于啥?
a4 = "D" 這個(gè)元素在子數(shù)組 ["D", "B", "A", "C"] 中是第幾大的元素。"A"是第0大的元素,"B"是第1大的元素,"C" 是第2大的元素,"D"是第3大的元素,所以 a4 = 3。
a3 = "B" 這個(gè)元素在子數(shù)組 ["B", "A", "C"] 中是第幾大的元素。"A"是第0大的元素,"B"是第1大的元素,"C" 是第2大的元素,所以 a3 = 1。
a2 = "A" 這個(gè)元素在子數(shù)組 ["A", "C"] 中是第幾大的元素。"A"是第0大的元素,"C"是第1大的元素,所以 a2 = 0。
a1 = "C" 這個(gè)元素在子數(shù)組 ["C"] 中是第幾大的元素。"C" 是第0大的元素,所以 a1 = 0。(因?yàn)樽訑?shù)組只有1個(gè)元素,所以a1總是為0)
所以,X(s1) = 3*3! + 1*2! + 0*1! + 0*0! = 20。

2、通過(guò)康托逆展開(kāi)生成全排列
  如果已知 s = ["A", "B", "C", "D"],X(s1) =?20,能否推出 s1 = ["D", "B", "A", "C"] 呢?
  因?yàn)橐阎?X(s1) = a4*3! + a3*2! + a2*1! + a1*0! = 20,所以問(wèn)題變成由 20 能否唯一地映射出一組 a4、a3、a2、a1?如果不考慮 ai 的取值范圍,有
3*3! + 1*2! + 0*1! + 0*0! = 20
2*3! + 4*2! + 0*1! + 0*0! = 20
1*3! + 7*2! + 0*1! + 0*0! = 20
0*3! + 10*2! + 0*1! + 0*0! = 20
0*3! + 0*2! + 20*1! + 0*0! = 20
等等。但是滿(mǎn)足 0 <= ai <= n-1 的只有第一組。可以使用輾轉(zhuǎn)相除的方法得到 ai,如下圖所示:

知道了a4、a3、a2、a1的值,就可以知道s1[0] 是子數(shù)組["A", "B", "C", "D"]中第3大的元素 "D",s1[1] 是子數(shù)組 ["A", "B", "C"] 中第1大的元素"B",s1[2] 是子數(shù)組 ["A", "C"]?中第0大的元素"A",s[3] 是子數(shù)組 ["C"] 中第0大的元素"C",所以s1 = ["D", "B", "A", "C"]。
這樣我們就能寫(xiě)出一個(gè)函數(shù),它可以返回? s 的第 m 個(gè)排列。

?

以下是代碼(以不超過(guò)10位的字符串為例),有所修改:

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 using namespace std; 6 const int maxn = 10; 7 char s[maxn+1]; 8 //計(jì)算x的階乘 9 int Cal(int x) 10 { 11 int ans = 1; 12 for (int i = 1; i <= x; i++) ans *= i; 13 return ans; 14 } 15 //得到字符在字符串其后字符中為第幾大 16 int ID(char* c, char*s,int len) 17 { 18 int re = 0; 19 for (char*t = c + 1; t < s + len; t++) 20 { 21 if (*c >= *t)re++; 22 } 23 return re; 24 } 25 //得到字符串康拓展開(kāi)值(從0開(kāi)始) 26 int V_CantorExpansion(char *s) 27 { 28 int ret = 0; 29 int len = strlen(s); 30 for (int i = 0; i < len; i++) 31 { 32 ret += ID(s+i,s,len)*Cal(len - i - 1); 33 } 34 return ret; 35 } 36 //求k個(gè)字符(升序)第n個(gè)全排列 37 string Inv_CantorExpansion(char*s, int n) 38 { 39 int len = strlen(s); 40 string ini = s; 41 string ret; 42 for (int i = len - 1; i>= 0; --i) 43 { 44 int pos = n / Cal(i); 45 ret.push_back(ini[pos]); 46 ini.erase(pos, 1); 47 n %= Cal(i); 48 } 49 return ret; 50 } 51 int main() 52 { 53 54 while (1) 55 { 56 printf("輸入不超過(guò)10位的字符串計(jì)算康拓展開(kāi)值:\n"); 57 scanf("%s", s); 58 printf("%d\n", V_CantorExpansion(s)); 59 printf("輸入不超過(guò)10位的初始字符串(升序)計(jì)算第n個(gè)全排列:\n"); 60 scanf("%s", s); 61 int n; 62 scanf("%d", &n); 63 printf("%s\n", Inv_CantorExpansion(s, n).c_str()); 64 } 65 return 0; 66 } View Code

?

轉(zhuǎn)載于:https://www.cnblogs.com/ivan-count/articles/7466044.html

總結(jié)

以上是生活随笔為你收集整理的【转】康拓展开的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。