【康拓展开&逆康托展开】

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sxy201658506207/article/details/84672836

 百度百科就够了

自己的体会:
康托展开是基于比他小的前面的个数来进行计算的
       另外康托展开也是一个数组到一个数的映射,因此也是可用于hash,用于空间压缩。比如在保存一个序列,我们可能需要开一个数组,如果能够把它映射成一个自然数, 则只需要保存一个整数,大大压缩空间。比如八数码问题。

欧拉项目上的第二四题就需要用逆康拓展开的,不过这道题不是说的自然数,包括0,所以构建数组的时候把0搞进去就好了
欧拉项目上记得不赞成贴code的,
 

#include <bits/stdc++.h>
using namespace std;
static const int fac[]={1,1,2,6,24,120,720,5040,40320,362880};//阶乘
int cantor(int *a,int n){	//康托展开
	int x=0;
	for(int i=0;i<n;++i){
		int smaller=0;	//当前位置之后小于它的个数
		for(int j=i+1;j<n;++j){
			if(a[j]<a[i])
				++smaller;
		}
		x+=fac[n-i-1]*smaller;
	}
	return x;
}
void decantor(int x,int n){
	std::vector<int> v;
	std::vector<int> a;
	for(int i=0;i<n;++i)	v.push_back(i);//这儿根据要求被排列的数字进行选择有那几个,不过要注意一下在0作为前导的时候
	for(int i=1;i<=n;++i)	v.push_back(i);
	for(int i=n;i;--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);		// 移除选做当前位的数
	}
	int sz=a.size();
	for(int i=0;i<sz;++i)
		cout<<a[i];
	cout<<endl;
}
int main(){
      cantor();
	  decantor(1000000-1,10);
}

猜你喜欢

转载自blog.csdn.net/sxy201658506207/article/details/84672836
今日推荐