标签:
        最近在搞新加坡的NOI2012的题,其中第二题Pancake可以用BFS解决,不过现在正在研究盖茨的《Bounds For Sorting By Prefix Reverse》,等研究出来一些成果会发布。目前能搞定的是BFS算法, 好在n最大为8,枚举量最多为8!,虽说有每个测试点可能有6000个测试数据,但还算可以接受。在BFS中,可以利用康托展开进行优化,本文主要对康托展开进行一下介绍。
        康托展开是一个全排列到自然数的双射,康托展开其实计算的是当前排列在全排列中由小到大的顺序(最小的顺序编号为0)。而且可以通过逆运算还原原值。
        康托展开公式:X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0!(其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n,a[i]指比第i个数字(姑且设为x)小(从右向左数)小且没在从左起到x之间出现过的数字的个数,换句话说,a[i]也就是从右数第i个数字的右面比它小的数字的个数)
        这样说这个公式可能让人难以理解,我们还是举一个例子吧。
        比如下面这个排列:3 5 7 4 1 2 9 6 8,第一个数是3,在3的右面有两个比它小的数,所以a[i]=2,第一项为2*8!,第二项是5,在5的右面有3个比它小的数,所以第二项是3*7!...以此类推,所以这个排列的康托展开2*8!+3*7!+4*6!+2*5!+0*4!+0*3!+2*2!+0*1!+0*0!=98884
        由于阶乘的出现,很明显在实际应用的过程中,n在10以内适用康托展开,因为如果n比较大的话,阶乘值也会很大,那么使用康托展开进行排列优化的意义就不大了,而且计算机存储也颇为不便。
        下面将给出把一个排列(排列的元素为从1~n)转化为康托展开和把康托展开转化成排列的C++程序:
 
-   
- #include<cstdio>    
- using namespace std;   
-   
- int n,bin[11],a[50001],b[50001],num;   
- bool t[50001];   
-     
- void create() 
- {   
-   int i;   
-   bin[0]=1;   
-   bin[1]=1;   
-   for(i=2;i<=10;i++)   
-     bin[i]=bin[i-1]*i;   
- }   
-   
- void atonum() 
- {   
-   int i,j;   
-   for(i=1;i<=n;i++)   
-     for(j=i+1;j<=n;j++)   
-       if(a[i]>a[j])   
-         b[i]++;   
-   num=0;   
-   for(i=1;i<=n;i++)   
-     num+=b[i]*bin[n-i];   
- }   
-   
- void numtoa() 
- {   
-   int i,yushu,div,temp;   
-   void translate();   
-   temp=num;   
-   for(i=1;i<=n;i++)   
-   {   
-     div=temp/bin[n-i];   
-     yushu=temp%bin[n-i];   
-     b[i]=div;   
-     temp=yushu;   
-   }   
-   b[n]=0;   
-   translate();   
- }   
-   
- void translate() 
- {   
-      int i,j,s;   
-      for(i=0;i<=n+1;i++)   
-        t[i]=true;   
-      a[1]=b[1]+1;   
-      t[a[1]]=false;   
-      for(i=2;i<=n;i++)   
-      {   
-        s=0;   
-        for(j=1;j<=n;j++)   
-          if(t[j]==true)   
-          {   
-            s++;   
-            if(s==b[i]+1)   
-            {   
-              a[i]=j;   
-              t[j]=false;   
-              break;   
-            }   
-          }   
-      }   
- }   
-   
- int main() 
- {   
-     freopen("cantor.in","r",stdin);   
-     freopen("cantor.out","w",stdout);   
-     int i,sign;   
-     create();   
-     scanf("%d",&sign);   
-     if(sign==1) 
-     {   
-       scanf("%d",&n);   
-       for(i=1;i<=n;i++)   
-         scanf("%d",&a[i]);   
-       atonum();   
-       printf("%d",num);   
-     }   
-     else 
-     {   
-       scanf("%d",&n);   
-       scanf("%d",&num);   
-       numtoa();   
-       for(i=1;i<=n;i++)   
-         printf("%d ",a[i]);   
-     }   
-     return 0;   
- }   
 
 
欢迎鄙视。
康托展开
标签:
原文地址:http://www.cnblogs.com/jerryxie/p/4780695.html