康托展开
康托展开面对的两个问题:
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*(n−1)!+a2*(n−2)!+⋯+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]; }
stay hungry stay foolish

浙公网安备 33010602011771号