首页 > 其他分享 >康托展开及康托逆展开运算总结

康托展开及康托逆展开运算总结

时间:2023-07-24 15:00:49浏览次数:41  
标签:及康托 排列 int 说明 数有 展开 康托


前文:

这个东西是我准备进攻一道Astar算法的八数码题目时,遇到的。

决定先搞懂这个,再进攻八数码(传说中那道不做人生不完整的题目)。

 

康托展开:

百度百科给出的定义是:康托展开是一个全排列到一个自然数双射,常用于构建哈希表时的空间压缩。 康托展开的实质是计算当前排列在所有由小到大全排列中的顺序,因此是可逆的。

 

简单的说就是用来判断一个数的一个全排列在它所有的全排列中是第几个。

它的运算规则就是:

康托展开及康托逆展开运算总结_数组

康托展开及康托逆展开运算总结_康托展开_02

为整数,并且

康托展开及康托逆展开运算总结_数组_03

康托展开及康托逆展开运算总结_康托展开_02

表示原数的第i位在当前未出现的元素中是排在第几个。

 

那这个东西有什么用呢?

假如你想要标记9的全排列,普通的方法就要开一个大小为10^9的数组,但是用康托展开只需要开大小为9!的数组就好了。

n位(0~n-1)全排列后,其康托展开唯一且最大约为n!,因此可以由更小的空间来储存这些排列。由公式可将X逆推出对应的全排列。它可以应用于哈希表中空间压缩,而且在搜索某些类型题时,将VIS数组量压缩。比如:八数码魔板

我们来举个例子

可以求出n的全排列中第x大排列。

如n=5,x=96时:

首先用96-1得到95,说明x之前有95个排列.(将此数本身减去1)

用95去除4! 得到3余23,说明有3个数比第1位小,所以第一位是4.

用23去除3! 得到3余5,说明有3个数比第2位小,所以是4,但是4已出现过,因此是5.

用5去除2!得到2余1,类似地,这一位是3.

用1去除1!得到1余0,这一位是2.

最后一位只能是1.

所以这个数是45321。

 

再举个例子说明。
在 (1,2,3,4,5)5个数的排列组合中,计算 34152的康托展开值。

首位是3,

则小于3的数有两个,为1和2,a[5] = 2 ,则首位小于3的所有排列组合为a[5] * (5 - 1)!,第二位是4

则小于4的数有两个,为1和2,注意这里3并不能算,因为3已经在第一位,所以其实计算的是在第二位之后小于4的个数。因此a[4] = 2第三位是1

则在其之后小于1的数有0个,所以a[3] = 0第四位是5

则在其之后小于5的数有1个,为2,所以a[2] = 1 最后一位就不用计算啦,因为在它之后已经没有数了,所以 固定为0

根据公式:

康托展开及康托逆展开运算总结_数组

所以比34152小的组合有61个,即34152是排第62。

康托展开实现代码:
 

fact[10];  //fact[i]存储i的阶乘的值
//把数组s合并为一个状态num, k代表数组长度
void cantor (int s[], ll &num, int k) 
{
    num = 0;
    for (int i = 0; i < k; i ++)
    {
        int cnt = 0;
        for (int j = i + 1; j < k; j++) 
            if (s[i] > s[j]) cnt++;
        num += fact[k - i - 1] * cnt;
    }
}

 

康托展开的逆:

康托展开是一个全排列到自然数的双射,可以作为哈希函数。

所以当然也可以求逆运算了。

对于上述例子,在(1,2,3,4,5) 给出61可以算出起排列组合为34152。由上述的计算过程可以容易的逆推回来,具体过程如下:

用 61 / 4! = 2余13,说明 

 说明比首位小的数有2个,所以首位为3。用 13 / 3! = 2余1,说明 

 ,说明在第二位之后小于第二位的数有2个,所以第二位为4。用 1 / 2! = 0余1,说明 

 ,说明在第三位之后没有小于第三位的数,所以第三位为1。用 1 / 1! = 1余0,说明 

 ,说明在第二位之后小于第四位的数有1个,所以第四位为5。

最后一位自然就是剩下的数2。

通过以上分析,所求排列组合为 34152。

康托逆展开代码实现:

int  fac[] = {1,1,2,6,24,120,720,5040,40320};
//康托展开的逆运算,{1...n}的全排列,中的第k个数为s[]
void reverse_kangtuo(int n,int k,char s[])
{
    int i, j, t, vst[8]={0};
    --k;
    for (i=0; i<n; i++)
    {
        t = k/fac[n-i-1];
        for (j=1; j<=n; j++)
            if (!vst[j])
            {
                if (t == 0) break;
                --t;
            }
        s[i] = '0'+j;
        vst[j] = 1;
        k %= fac[n-i-1];
    }
}

 

标签:及康托,排列,int,说明,数有,展开,康托
From: https://blog.51cto.com/u_16131191/6835273

相关文章

  • 康托展开
    这应该是数学吧?康托展开要求的就是解决排列问题的一种数学,具体解决的是一组数的一个合法排列在这组数的全部排列中的排名应该就只能解决这个吧?它的解决方式也挺简单的,有一个比较方便的公式$$ans=\sum_{i=1}^{n}sum_{ai}*(n-i)!$$感性理解一下:比如有一个序列\(2,4......
  • linux 中 根据制定列标签展开为两列以及依据两列信息进行合并
     001、[root@PC1test05]#lsresult.txt[root@PC1test05]#catresult.txt##测试数据223669237092235172369632351523708323556237134234762371142362223720......
  • 关于Antd中table列Fixed导致的expandedRowRender展开行错位问题
    右侧操作列的属性为fixed:'right'在展开行时出现列错位的问题打开element发现列属性设置为fixed后在DOM中是独立出来的解决办法:<a-table:columns="columns":data-source="data"bordered:pagination="false":scroll="{......
  • vue+element-ui 点击表格某一行,展开内容
    正常情况下,表格中想要展开某一行只能通过点击最前面的小箭头,如果想要实现点击某一行后直接展开,那么首先,就要先了解这几个属性:row-key的值只能是表格中某一列的key,而expand-row-keys数组里保存的则是所有展开行的row-key值,假如设置row-key=“id”,那么expand-row-keys数组......
  • 【组合数学】康托展开 学习笔记
    康托展开将\(1...n\)的所有排列按照字典序进行排序,某个排列的排名可以通过康托展开的方法求出。原理观察排列\(2,3,1,4\)和\(2,3,4,1\),发现第一个不同的位置是第三位,而且第一个排列的第三位比第二个小,根据字典序的性质,第一个排列的排名在第二个之前。从这里我们也可以发......
  • css 超出行显示展开收起
    显示展开收起:<divclass="wrapper"><inputid="exp111"class="exp"type="checkbox"><divclass="text">......
  • 利用g++展开宏
    参考ACM学习其他人的代码时,遇到一些不习惯的宏定义方式,影响理解,但由无法直接查找替换,这里用g++将宏展开;g++-Einput_file.cpp-ooutput_file.cpp得到进行宏展开后的文件output_file.cpp;注意,其中也包含include的库文件.......
  • 康托展开
    简介:康托展开可以求解一个排列的序号,比如:12345序号为1 ,12354序号为2,按字典序增加编号递增,依次类推。康托逆展开可以求解一个序号它对应的排列是什么。 康托展开解释:先给出康托展开的公式:                          ......
  • 2023-07-13:如果你熟悉 Shell 编程,那么一定了解过花括号展开,它可以用来生成任意字符串
    2023-07-13:如果你熟悉Shell编程,那么一定了解过花括号展开,它可以用来生成任意字符串。花括号展开的表达式可以看作一个由花括号、逗号和小写英文字母组成的字符串定义下面几条语法规则:如果只给出单一的元素x,那么表达式表示的字符串就只有"x"。R(x)={x}例如,表达式"a"......
  • elment ui展开行嵌套表格 进行修改数据后展开行自动收起
    https://it.cha138.com/python/show-74200.html tags:篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ElmentPlus表格展开行后,进行修改数据后展开行自动收起相关的知识,希望对你有一定的参考价值。ElmentPlus表格展开行后,进行修改数据后展开行自动收起场景:在......