康托展开与康托逆展开

大佬的讲解
康托展开 : 解决一些序列问题的算法;
用于求当前序列在按照字典序排序的全排列的情况下,排在第几位;
康托展开是一个全排列到自然数的双射;可用于哈希表的压缩;
//(反正我不会);
//它可以应用于哈希表中空间压缩,
//而且在搜索某些类型题时,将VIS数组量压缩。比如:八数码、魔板。。
//(我也不知道啥意思)

#include 
int a[3]={2,3,1};
using namespace std;
int fxi[8]={1,1,2,6,24,120,720,5040};
int main()
{
    int ans=0;
    for(int i=0;i<3;++i)
    {
        int m=0;
        for(int j=i+1;j<3;++j)
        {
            if(a[j]<a[i])
                m++;
        }
        ans=ans+m*fxi[3-1-i];
    }
    cout<<ans+1<<endl;
    return 0;
}

逆康托展开

static const int FAC[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};    // 阶乘

//康托展开逆运算
void decantor(int x, int n)
{
    vector<int> v;  // 存放当前可选数
    vector<int> a;  // 所求排列组合
    for(int i=1;i<=n;i++)
        v.push_back(i);
    for(int i=m;i>=1;i--)
    {
        int r = x % FAC[i-1];
        int t = x / FAC[i-1];
        x = r;
        sort(v.begin(),v.end());// 从小到大排序 
        a.push_back(v[t]);      // 剩余数里第t+1个数为当前位
        v.erase(v.begin()+t);   // 移除选做当前位的数
    }
}
用途

n位(0~n-1)全排列后,其康托展开唯一且最大约为n!,因此可以由更小的空间来储存这些排列。由公式可将X逆推出唯一的一个排列。

你可能感兴趣的:(康托展开与康托逆展开)