康托展开

康托展开面对的两个问题:

1.在1234所有的全排列中求某一排列是第几个。

2.求第n个排列时怎么样的。

 

1.康托展开

其实想法很简单比如2 3 4 1,rank=0;

i=0时是a[i]=2,后面小的数有1,如果1在第一位肯定是在这个序列前面,然后后面的3个数进行全排类3!,rank+=1*3!

i=1时a[i]=3,后面比小的数有1,选择1在这一位,rank+=1*2!

i=2时a[i]=4,后面小的有1,选择1在这一位,rank+=1*1!

i=3时rank+=0*0!;

最后rank++;原因是如果是1234 rank=0但是是一种;

总结的rank公式如下:rank=a1*(n1)!+a2*(n2)!++an*0!   (a1-an是比后面比这个数小的个数)

#include<stdio.h>
#include<iostream>
#include<algorithm>
#define N 100
using namespace std;
int contor(int permutation[],int n){
    int factor[10]={1,1,2,6,24,120,720,5040,40320,362880};//阶层
    int i,j,count,rank;
    rank=0;
    for(i=0;i<n;i++){
        count=0;
        for(j=i+1;j<n;j++){
            if(permutation[j]<permutation[i])count++;
        }
        rank+=count*factor[n-i-1];
    }
    return rank+1;
}
int main(){
    int a[N],n;
    cin>>n;
    for(int i=0;i<n;i++)cin>>a[i];
    cout<<contor(a,n);
    return 0;
} 

 2.逆康托展开

  公式的rank是从0开始计算的 所有rank- -

  将字符排序1 2 3 4

  • 用 9 / 3! = 1余3,说明a1=1,说明比首位小的数有1个,所以首位为2。
  • 用 3 / 2! = 1余1,说明a2=1,说明在第二位之后小于第二位的数有1个,所以第二位为3。
  • 用 1 / 1! = 1余0,说明a3=1,说明在第三位之后有1个小于第三位的,所以第三位为4。
  • 最后一位自然就是剩下的数1啦。
  • 通过以上分析,所求排列组合为 2341。
void decontor(int standard[],int n,int rank){
    int i,num,t;
    int factor[10]={1,1,2,6,24,120,720,5040,40320,362880};
    vector<int> v;
    vector<int> a;
    rank--;
    sort(standard,standard+n);
    for(i=0;i<n;i++)v.push_back(standard[i]); 
    for(i=0;i<n;i++){
        t=rank/factor[n-i-1];
        rank=rank%factor[n-i-1];
        a.push_back(v[t]);
        v.erase(v.begin()+t);
    }
    for(i=0;i<n;i++)cout<<a[i];
} 

 

posted @ 2020-11-09 20:44  金龙喩  阅读(115)  评论(0)    收藏  举报