康拓展开/全排列散列(俞勇板子)

首先可以参考这一篇博文传送门,这篇博文说的很好,大多数康拓展开都是这样写的,但是俞老师的板子是正好反着进行判断一次,不过也是很好的,附上俞老师的注释与板子

任务:对一个N的全排列,返回一个整数代表它在所有排列中的排名,同样对于一个排名返回原排列,排名从0到N!-1

说明:把排列看成一个多进制数,第i位的进制是(N-i)!。设a[i]=x,前i-1个有k个比x小,那么这一位应该用(i-1-k)*(N-i)!来作为权值,最后加上所有位的权值即可。

用数求排列的时候,从高位到低位一位一位确定,用这一位的权值除以这一位对应的阶乘,若为k,那么从还没用过的数中找出第k+1小的即可。

附上代码:


#include<bits/stdc++.h>

using namespace std;

const int maxn=10;

int n,factorial[maxn];

void fac()
{
    factorial[0]=1;
    factorial[1]=1;
    for(int i=2;i<=n;i++){
        factorial[i]=factorial[i-1]*i;
    }
}

void intToArray(int x,int a[maxn])
{
    bool used[maxn];
    int i,j,temp;
    for(i=1;i<=n;i++){
        used[i]=false;
    }
    for(i=1;i<=n;i++){
        temp=x/factorial[n-i];
        for(j=1;j<=n;j++){
            if(!used[j]){
                if(temp==0){
                    break;
                }
                --temp;
            }
        }
        a[i]=j;
        used[j]=true;
        x%=factorial[n-i];
    }
}

int arrayToInt(int a[maxn])
{
    int i,j,ans=0,temp;
    for(int i=1;i<=n;i++){
        temp=a[i]-1;
        for(int j=1;j<i;j++){
            if(a[j]<a[i]){
                temp--;
            }
        }
        ans+=factorial[n-i]*temp;
    }
    return ans;
}

int main()
{
    scanf("%d",&n);
    fac();
    int x,a[maxn];
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/84430271