全排列编码于解码-康托展开式

在一些问题中需要对全排列状态进行编码,如果使用完美hash来实现的话需要编码数量在计算机承受范围内,康托展开式符合条件

公式:X=An*(n-1)!+An-1*(n-2)!+......A2*1!+A1*0!

其中An等于在剩余元素中当前元素第几大(从0开始)。
比如:1 4 2 6 5 3 7 8 9

1在剩下的1 4 2 6 5 3 7 8 9中为第0大

4在剩下的4 2 6 5 3 7 8 9中为第2大

2在剩下的2 6 5 3 7 8 9中为第0大

..........

8在8 9中为第0大

9在9中为第0大

则编码为0*8!+2*7!+0*6!+2*5!+1*4!+0*3!+0*2!+0*1!+0*0!=10344

解码

辗转对n!作商和取余,商代表下一个位置元素在未选出元素中排第几大,举例

10344/8!=0

10344%8!=10344

10344/7!=2

10344%7!=264

264/6!=0

264%6!=264

264/5!=2

264%5!=24

24/24!=1

24%24=0

0/3!=0

.........

0%0!=0

1在1 2 3 4 5 6 7 8 9中排第0大

4在2 3 4 5 6 7 8 9中排第2大

2在2 3 5 6 7 8 9中排第0大

6在3 5 6 7 8 9中排第2大

5在3 5 7 8 9中排第1大

3在3 7 8 9中排第0大

7在7 8 9中排第0大

8在8 9中排第0大

9在9中排第0大

所以10344对应的排列为1 4 2 6 5 3 7 8 9

代码:

[cpp] view plain copy

    1. #include<iostream>
    2. #include<vector>
    3. using namespace std;
    4. const long long maxN=363000;
    5. const long long p[]={1,1,2,6,24,120,720,5040,40320};
    6. long long coding(int* u){
    7. long long code=0;
    8. for(int i=0;i<9;i++){
    9. int k=0;
    10. for(int j=i+1;j<9;j++)if(u[i]>u[j])k++;
    11. code+=k*p[8-i];
    12. }
    13. return code;
    14. }
    15. vector<int> decoding(long long code){
    16. bool vis[9]={0};
    17. vector<int> ans;
    18. for(int i=8;i>=0;i--){
    19. int u=code/p[i],v=0;code%=p[i];
    20. while(u>=0){
    21. if(vis[v]==false)u--;
    22. v++;
    23. }
    24. ans.push_back(v);
    25. vis[v-1]=true;
    26. }
    27. return ans;
    28. }
    29. int main(){
    30. int u[]={1,4,2,6,5,3,7,8,9};
    31. int code=coding(u);
    32. vector<int> ans=decoding(code);
    33. cout<<"code:"<<code<<endl<<"decode:";
    34. for(int i=0;i<ans.size();i++)cout<<ans[i]<<‘ ‘;
    35. }

原文地址:https://www.cnblogs.com/TAMING/p/8538874.html

时间: 2024-08-14 20:27:22

全排列编码于解码-康托展开式的相关文章

全排列的编码与解码——康托展开

.康托展开:全排列到一个自然数的双射 X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! ai为整数,并且0<=ai<i(1<=i<=n) 适用范围:没有重复元素的全排列 二.全排列的编码: {1,2,3,4,...,n}的排列总共有n!种,将它们从小到大排序,怎样知道其中一种排列是有序序列中的第几个? 如 {1,2,3} 按从小到大排列一共6个:123 132 213 231 312 321.想知道321是{1,2,3}中第

康托展开式[美味的全排列]

对于全排列问题,比如说 对于一个集合{a,b,c,d,e,f,g},所有可能的排列方式是{a,b,c,d,e,f,g},{a,b,c,d,e,g,f},{a,b,c,d,f,e,g},....,{g,f,e,d,c,b,a} 好吧,如果现在要写一个哈希映射关系表来实现对于每一种排列可能的映射,那么少不了需要设计一个哈希函数(以什么作为key,怎么尽可能减小空间浪费....都是需要好好思考的问题). 有趣的是,对于这样的全排列问题,康托展开法带来了一种几乎完美的函数映射关系(一一映射&&双射

全排列的编码与解码

看<算法竞赛入门经典> 第七章, 隐式图的遍历,八数码一题. 学到了全排列的编码与解码. 用处: 每一个排列代表一个图的状态, 比如 8,3,2,4,5,6,7,0,1 表示成图就是 8 3 2 4 5 6 7 0 1 我们将0-8的全排列和0-9!一一映射起来. 比如0, 1, 2, 3, 4, 5, 6, 7, 8 对应的就是0, 因为是第一个排列组合 那么8 7 6 5 4 3 2 1 0 对应的就是9!,因为是最后一种排列组合. 算法实现如下: int fact[9]; //假设排列组

NYOJ 139 我排第几个 康托展开式

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=139 思路:康托展开式的典型应用,康托展开式是什么呢,举个例子.1,2,3这三个数的全排列共有六种,那么按照字典的顺序,『3,2,1』 这个序列是在第几个呢.康托是这样想的:   首先从第一位3开始看,比3小的有2,1,那么也就是说如果第一位是1或者2都在这个序列的前面,那么以1或者2开头的序列有多少呢,答案为2*2!.为什么是这个答案呢?因为符合 要求的第一位共有1和2两个数,然后第二

Python学习笔记八:文件操作(续),文件编码与解码,函数,递归,函数式编程介绍,高阶函数

文件操作(续) 获得文件句柄位置,f.tell(),从0开始,按字符数计数 f.read(5),读取5个字符 返回文件句柄到某位置,f.seek(0) 文件在编辑过程中改变编码,f.detech() 获取文件编码,f.encoding() 获取文件在内存中的编号,f.fileno() 获取文件终端类型(tty.打印机等),f.isatty() 获取文件名,f.name() 判断文件句柄是否可移动(tty等不可移动),f.seekable() 判断文件是否可读,f.readable() 判断文件是

win api 实现 base64编码、解码

最近在写小玩意,用到了base64编码,但是考虑到体积大小,网上的多种实现都是利用开源的代码,这就增加了其大小.我想win api能不能实现base64编码.解码.通过一通乱搜,还有收获.就有了以下代码 #pragma comment(lib,"crypt32.lib") LPSTR Base64Encode(LPBYTE lpBuffer,DWORD dwLen) { DWORD dwNeed; LPSTR lpBase64Str ; DWORD dwIndex ; DWORD dw

了解URL编码的基本概念,在javascript和java程序中使用内置的API进行编码和解码

1.URL编码的基本概念 URL只能使用US-ASCII 字符集来通过因特网进行发送.由于URL常常会包含 ASCII 集合之外的字符,URL必须转换为有效的 ASCII 格式.URL 编码使用 "%" 其后跟随两位的十六进制数来替换非 ASCII 字符.URL 不能包含空格,URL 编码通常使用 + 来替换空格.所谓URL编码,就是将非US-ASCII字符和US-ASCII中的特殊字符,用相应的字符集编码来表示.比如,汉字"你",如果用UTF-8编码,出现在URL

【转】C/C++ URL编码,解码(提取自PHP)

//解码 //头文件自己加上的 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <string> #include <iostream> using namespace std; /* {{{ php_htoi  */ static int php_htoi(char *s) { int value; int c; c = ((unsigned char *)

H.264硬编码&硬解码

Firefly-RK3288拥有强大的VPU(视像处理器),能够流畅实现720P和1080P视频的H.264编解码: 而H.264的压缩率更高,可以更大程度更小视频的空间占用. 详细看视频演示 1. 演示介绍 基于Firefly开发板:视频监控演示: 需要两块开发板:一块开发板摄像头采集+硬编码,网络传输. 另一块开发板 网络接收.硬解码+显示. Demo中采样5GHz Wi-Fi传输,摄像头使用OV13850,或UVC camera 2. H.264技术介绍 H.264是一种高性能视频编解码技