定义:

把一个整数X展开成如下形式:
X=a[n] ∗ *(n-1)!+a[n-1]∗*(n-2)!+…+a[i]*(i-1)!+…+a[2]*1!+a[1]*0![1]
其中a[i]为当前未出现的元素中是排在第几个(从0开始),并且0<=a[i] < <script type="math/tex" id="MathJax-Element-119"><</script>i(1<=i<=n)

应用

求一个数字串排列在字典序下的编号(即第几个)。当然也可以倒着用,即给你编号求数字串。
可以对一些算法进行优化,有点hash的味道。

实现:

①求一个数字串排列在字典序下的编号:

其实定义里头的那个公式求的就是排列a之前的排列数。代码模拟一下即可。
这里采用的是递归实现:

long long dfs(int x){if (x>n)return 0;long long sum=0;int num=0;for (int i=1;i<a[x];i++)if (!f[i])//如果这个数并没有出现过num++;f[a[x]]=true;sum+=num*jc[n-x];//jc[i]即i的阶乘sum+=dfs(x+1);//递归return sum;
}

②倒着用:

反过来想,对于当前的编号n,我们要取的数。
不难发现,第n位的数即为num/jc[sum-n]。

仍然为递归实现:

void dfs1(long long x,int num){if (num==n){//因为题目要求行末不能有空格for (int i=1;i<=n;i++)//最后一个数字其实已经确定,即仍然没有出现的那个if (!f[i]){printf("%d",i);break;}return;}int dd=x/jc[n-num];int now=dd;for (int i=1;i<=n;i++){if (!f[i])if (dd==0){printf("%d ",i);f[i]=true;break;}elsedd--;}dfs1(x-now*jc[n-num],num+1);//递归
}

③算法优化:

这里举一个最经典的例子:八数码问题。

给出一个3*3的矩阵,其中有一个格子是空格,其他都是数字,每次移动可以将格子附近的数字移到格子中,同时原先的数字变成格子。给定一个初始状态和最终状态,求最少步数。

当然,这道题的解法很多,但这里只讲康托展开。
简单的BFS的话是会T掉的,因为判重的问题。而康托展开在这道题中的作用就是判重。把3*3的序列转化为其字典序,就能够存的下了(jc[9]=362880,即有不到40万的状态)。判重也就能实现了。

代码(写的太烂,跑得比较慢,二维压成一维就可以省去我的calc的过程):

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 3
#define MAXM 400000
using namespace std;
const int t1[4]={0,1,0,-1};
const int t2[4]={1,0,-1,0};
bool num[MAXM+5];
int que[MAXM+5][2];
int a[MAXN+5][MAXN+5],b[MAXN+5][MAXN+5],jc[MAXN*MAXN+5];
int n=3;
bool f[MAXM+5];
int calc(int s[MAXN+5][MAXN+5]){int sum=0;for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)sum=sum*10+s[i][j];return sum;
}
void fz(int s[MAXN+5][MAXN+5],int zhi,int &x,int &y){for (int i=n;i>=1;i--)for (int j=n;j>=1;j--){s[i][j]=zhi%10;zhi/=10;if (s[i][j]==0){x=i; y=j;}}
}
int jisuan(int x){//康托展开memset(f,false,sizeof(f));int s[MAXN*MAXN+5];for (int i=MAXN*MAXN;i>=1;i--){s[i]=x%10;x/=10;}int sum=0;for (int i=1;i<=MAXN*MAXN;i++){int num=0;for (int j=0;j<s[i];j++)if (!f[j])num++;f[s[i]]=true;sum+=num*jc[MAXN*MAXN-i];}return sum;
}
int main(){for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)scanf("%d",&a[i][j]);//初始状态for (int i=1;i<=n;i++)for (int j=1;j<=n;j++)scanf("%d",&b[i][j]);//目标状态jc[1]=1;for (int i=2;i<=MAXN*MAXN;i++)jc[i]=jc[i-1]*i;//算阶乘int r=0,w=1;que[1][1]=calc(a);que[1][0]=1;memset(num,0,sizeof(num));while (r<w){//BFSint xx[MAXN+5][MAXN+5];int x,y;memset(xx,0,sizeof(xx));if (que[++r][1]==calc(b)){printf("%d\n",que[r][0]);break;}fz(xx,que[r][1],x,y);for (int i=0;i<=n;i++){int p=x+t1[i],q=y+t2[i];if (p>=1&&p<=3&&q>=1&&q<=3){swap(xx[x][y],xx[p][q]);int l=calc(xx);int k=jisuan(l);if (!num[k]){que[++w][1]=calc(xx);que[w][0]=que[r][0]+1;num[k]=true;}swap(xx[x][y],xx[p][q]);}}}return 0;
}

康托展开(八数码问题)相关推荐

  1. A_Star 康托展开 八数码问题

    A_Star算法是一个主要用bfs实现的寻路算法,当数据量庞大的时候往往有更高的时间效率,可以看成是Dijkstra算法的升级版. "盲目搜索会浪费很多时间和空间, 所以我们在路径搜索时, ...

  2. 【 HDU1043-经典BFS+康拓展开 八数码】 (待更)

    给定一个序列,由1~8数字和字母x组成,表示的是一个3*3的矩形.每次操作x都能与相邻的数字交换,问如何操作才能使得序列为{1,2,3,4,5,6,7,8,x}. //多组数据-需要计算全部路径后直接 ...

  3. 康托展开与八数码问题

    康托展开的公式是 X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! 其中,ai为当前未出现的元素中是排在第几个(从0开始). 用康托展开将排列 ...

  4. 1043 Eight(八数码问题 康托展开 A*算法)

    首先介绍一下A*算法: https://blog.csdn.net/qq_40061421/article/details/81915573 然后是康托展开: https://blog.csdn.ne ...

  5. HDU 1043 Eight(双向BFS+康托展开)

    http://acm.hdu.edu.cn/showproblem.php?pid=1043 题意:给出一个八数码,求出到达指定状态的路径. 思路:路径寻找问题.在这道题里用到的知识点挺多的.第一次用 ...

  6. 【康拓展开逆康托展开】

    百度百科就够了 自己的体会: 康托展开是基于比他小的前面的个数来进行计算的        另外康托展开也是一个数组到一个数的映射,因此也是可用于hash,用于空间压缩.比如在保存一个序列,我们可能需要 ...

  7. HDU 1043 Eight(八数码)

    HDU 1043 Eight(八数码) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Oth ...

  8. [总结] 康托展开及其逆运算

    这里先贴一道例题 我们先科普一下康托展开 定义: X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! ai为整数,并且0<=ai<i ...

  9. 多种方法求解八数码问题

    AI的实验报告,改了改发上来.希望路过的大牛不吝赐教.非常是纳闷我的ida*怎么还没有双搜快.还有发现基于不在位启示的A*和Ida*都挺慢.尤其是ida* 搜索31步的竟然要十几秒.是我写的代码有问题 ...

最新文章

  1. 一行代码发一篇 ICML?
  2. 写过Mybatis插件?那说说自定义插件是如何加载的吧?
  3. mysql5.5.20安装图解_mysql5.5.20的安装步骤
  4. axios get怎么还会显示跨域_在Vue中如何使用axios跨域访问数据
  5. mfc怎么显示jpg png图像
  6. java原理—反射机制
  7. mysql 1033 frm_MySQL ERROR 1033 (HY000): Incorrect information in file. 处理一例
  8. git flow 命名规范 驼峰_图解ThinkPHP5框架(一):基础知识,开发规范与目录结构
  9. java 包的package和import语句
  10. 汽车行业如何进行数字化转型
  11. Docker入门学习
  12. WebCrack:一键自动化日站工具 ——yzddMr6
  13. 关于Android端模拟登陆教务系统
  14. 图解AUTOSAR(四)——基础软件层(BSW)
  15. zyt-python
  16. Sql 存储过程传递参数
  17. wireshark 学习更进一步 之wireshark异常数据解读
  18. 【web项目】前端生日礼物--clock篇
  19. 常规工具类:GeneralUtils.java
  20. 小程序生成图片保存到系统相册_电子相册怎么做 快速制作电子相册方法

热门文章

  1. 什么是AP,胖瘦AP如何区分?
  2. SideWinder诱饵文档加密流量分析
  3. 四川计算机二级时间安排,2020年3月四川计算机二级考试时间
  4. 【转】Java 8新特性(四):新的时间和日期API
  5. 总结 — 键盘输入特殊字符
  6. 微信小程序跳转报错errMsg: “navigateTo:fail webview count limit exceed“
  7. IPS的原理以及使用手册(cisco4240)
  8. Python spider (二) Requests Lxml bs4
  9. 安卓中两种压缩图片详解(比例压缩与质量压缩)
  10. 如何用纯 CSS 创作闪闪发光的霓虹灯文字