康托展开

康托展开

康托展开就是一种特殊的哈希函数,它的使用范围是对于n个数的排列进行状态的压缩和存储,例如要对9的全排列进行判重.没有必要

开一个10^9的数组,同时内存也不允许开到那么大的数组.对此,有人提出了优化,即对于一个n的排列数,没有必要开到10^n,因为在一个排列中每个数只出现一次,所以只要前n-1位确定了,前N位就确定了.

但是以上的想法仍不是可行的,因为N可以很大,例如15,所以便引入了康托展开:只需要确定这个排列在总的排列情况中是第几小的就可以了.

例如:我想知道321是{1,2,3}的排列中第几个大的数可以这样考虑 第一位是3,当第一位的数小于3时,那排列数小于321 如 123 213 小于3的数有1,2 所以有2*2!个 再看小于第二位2的 小于2的数只有一个就是1 所以有1*1!=1 所以小于321的{1,2,3}排列数有2*2!+1*1!=5个所以321是第6个大的数。 2*2!+1*1!是康托展开.

下面给出康托展开的代码:

C++代码:

1 fumction ktzk(s:zrr):longint;
2  var i,time,j:longint;
3 begin
4 for i:= 1 to 12 do
5 begin
6 time:=0;
7 for j:= i+1 to 12 do
8 if (s[j]>s[i]) then inc(time);
9 inc(ktzk,mi[12-i]*tot);
10 end;
11 end;

 

int hash(s[12])
{
    int ktzk=0;
    for (int i=1;i<=12;i++)
    {
        int tot=0;
        for (int j=i+1;j<=12;j++)
          if (s[j]>s[i]) tot++;
        ktzk+=(tot*mi[12-i]);//mi[I]数组中记录了i的阶乘. 
    }
    return ktzk;
}  
PASCAL代码:

 下面介绍几道需要用到康托展开的题目:8数码问题,USACO3.2.5

 

foreverzsz原创,转载请注明出处.

本文出处:http://www.cnblogs.com/foreverzsz/archive/2010/11/10/1874139.html

 

 

posted @ 2010-11-10 19:25  forever zsz  阅读(1297)  评论(1编辑  收藏  举报