康托展开&逆康托展开 代码实现

关于康托展开可以参考:

(60条消息) 康托展开和逆康托展开_哈希康托逆展开_wbin233的博客-CSDN博客

下面是我的代码实现:

康托展开:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;

int fac(int n){//计算阶乘的函数
    int i,ans=1;
    for(i=1;i<=n;i++)ans*=i;
    return ans;
}

int main(){
    int i,j;
    int n;//位数
    cin>>n;
    vector<int > ch(n+1,0);//填充一位,目的是使下标从1开始
    for(i=1;i<=n;i++)cin>>ch[i];//依次读入待转化的数字各位
    vector<int > mark(ch.size(),0);
    for(j=1;j<=n;j++){//规定正序为从左向右递增,求各数位的逆序数
        for(i=j+1;i<=n;i++){
            if(ch[i]<ch[j])mark[j]++;
        }
    }
    //ch     5  2  4  1  3  
    //mark   4  1  2  0  0 
    //阶乘   4!3!2!1!0
    int key=0;//key为转化后的数(序号)
    for(i=1,j=n-1;i<=n-1;i++,j--){//因为最后一次一定为0*...因此直接省略
        key+=mark[i]*fac(j);
    }
    cout<<key+1;

    return 0;
}

输入输出样例:

逆康托展开:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int fac(int n){//计算阶乘的函数
    int i,ans=1;
    for(i=1;i<=n;i++)ans*=i;
    return ans;
}

void search(int shang,int n,vector<int > &mark,vector<int > &ori){
    int i,j;
    int temp[n+1]={0};
    for(i=1;i<=n;i++){
        if(mark[i]==1)continue;
        for(j=1;j<=n;j++){
            if(mark[j]==1)continue;
            if(j<i)temp[i]++;
        }
    }
    for(i=1;i<=n;i++){
        if(temp[i]==shang&&mark[i]!=1){
            mark[i]=1;
            ori.push_back(i);
            return;
        }
    }
}

int main(){
    int n,key,i,j;
    cin>>n>>key;
    vector<int > ori(1,0);//储存答案//下标从1开始
    vector<int > mark(n+1,0);
    key--;
    for(i=1,j=n-1;i<=n;i++,j--){
        int temp=fac(j);
        int shang=key/temp;
        key=key%temp;
        search(shang,n,mark,ori);
    }
    for(i=1;i<=n;i++)cout<<ori[i];
    
    return 0;
}

输入输出样例:

The end!

猜你喜欢

转载自blog.csdn.net/Cat_ind/article/details/129577998