康托展开和康托展开的逆运算

八数码问题不用康托展开判断重复8s,用康托展开判断重复30MS。康托展开最大最明显的作用就是在判断状态是否重复方面了,其实属于hash的一个技巧。

一、康托展开

【问题背景】对于一个有n个不同元素的集合{1,2,3,4,...,n}的从小到大排序(从大到小 同理)的全排列 显然它有n!项。如n=4,那么就有4!=4×3×2×1=24项。

与自然数1,2,3,4,-----n!与之一一对应。比如  1~4四个数的全排列按字典序如下:

1234:第1个
1243:第2个
1324:第3个
1342:第4个
1423:第5个
1432:第6个
2134:第7个
2143:第8个
2314: 第9个
2341:第10个
2413:第11个
2431:第12个
3124:第13个
3142:第14个
3214:第15个
3241:第16个
3412:第17个
3421:第18个
4123:第19个
4132:第20个
4213:第21个
4231:第22个
4312:第23个
4321:第24个

【主要问题】

例1:求4132是第几个排列? 看上面就知道答案就是:20。 那么是怎么算的呢?

解:总共4个数,所以n=4.ans:=0;

第一个数是4,研究比4小的并且还没有出现过的数有3个:1,2,3。那么ans:=ans+ 3*(n-1)!

所以  ans:= ans+ 3*  3*2*1  =18

第二个数是1,研究比1小的并且还没有出现过的数为 0个。那么ans:=ans+ 0 * (n-2)!,那么ans不变。

第三个数是3,研究比3小的并且还没有出现过的数为1个:2。那么ans:=ans+ 1* (n-3)!,那么ans:=18+1* 1=19

第四个数是2,研究比2小的并且还没有出现过的数为0个。那么ans不变。其实最后一个可以不研究了,比它大和比它小的全都出现过了。 最后ans怎么等于19啊??代表它前面有19个排列嘛,那么4132自己就是第20个罗( 最后ans:=ans+1)

例2:问45231是第几个排列?

        4       5      2       3       1 

ans:= 3*4!  +  3*3!  +  1*2!  +  1*1!  +  0*0!  +  1  =94

练习

第一题:找出35142在1~5从小到大全排序中的位置?

第二题:找出64827315在1~8从小到大全排列中的位置?

第三题:找出35142在1~5从大到小全排序中的位置?

第四题:找出64827315在1~8从大到小全排列中的位置?

二、康托展开的逆运算

我把之前的div改为/,div是pascal语言的运算符号,/是C++的,意思都一样就是求两个整数除法运算后的商(不理会余数)

例3:1~5从小到大全排列中,找出第96个排列?

解:首先设x1x2x3x4x5, (x1等于?不知道),用96-1得到95,表示x1x2x3x4x5前面有95个序列。

第一个数x1,假设x1目前有k个比x1小的并且还没有出现过的数,那么

k:= 95 / (n-1)! = 95 / 24=3, 也就是有3个比x1小并且没有出现过的数,那么x1=4.

95变成95-3×24=23

第二个数x2,假设x2目前有k个比x2小的并且还没有出现过的数,那么

k:= 23 / (n-2)! = 23 / 6 = 3, 也就是有3个比x2小并且没有出现过的数,那么x2=5.(有3个数比它小的数是4,但4已经在之前出现过了,所以是5)

23变成 23 – 3 * 6 = 5

第三个数用5去除2! 得到2余1,那第三个数就是还没有出现过的第3小的数3(5变成1)

第四个数用1去除1! 得到1余0,那第四个数就是还没有出现过的第2小的数2

第五个数就是最后还没有出现的那个。

所以这个数是45321

练习:

第五题:8个数从小到大排序,求第28017个排列?

解:首先设x1x2x3x4x5x6x7x8, (x1等于?不知道),用28017-1得到28016,表示x1x2x3x4x5x6x7x8前面有28016个序列。

第一个数x1,假设x1目前有k个比x1小的并且还没有出现过的数,那么 k= 28016 / (8-1)! = 28016 / 5040=5(28016除以5040等于5,不理余数), 也就是有5个比x1小并且没有出现过的数,那么x1=6.28016变成28016 - 5040*5=2816

第二个数x2,假设x2目前有k个比x2小的并且还没有出现过的数,那么k= 2816/ (n-2)! = 2816 / 720 = 3, 也就是有3个比x2小并且没有出现过的数,那么x2=4.2816变成 2816– 3 * 720 = 656

关键是理解好第三个数,为什么是8.

第三个数x3,假设x3目前有k个比x3小的并且还没有出现过的数,那么k= 656/ (n-2)! = 656 / 120 = 5, 也就是有5个比x3小并且没有出现过的数,那么x3=?.

1(还没出现过)

2(还没出现过)

3(还没出现过)

4(出现过)

5(还没出现过)

6(出现过)

7(还没出现过)

8(还没出现过)

1、2、3、5、7(这五个还没有出现过),所以答案是x3=8

by scy

猜你喜欢

转载自blog.csdn.net/aliyonghang/article/details/128261637