1.生成全排列


第一类:按字典序生成

参考:

http://www.cnblogs.com/pmars/archive/2013/12/04/3458289.html

1.字典序法

通过一个已知排列,生成下一个,实质是改变尽量短的后缀,使两个排列的差尽量小。

步骤:

1.从右至左选出第一个i,p[i]<p[i+1];

2.从右至i,选出第一个j,p[i]<p[j];

3.交换p[i],p[j];

4.倒置i+1~n ;

#include<stdio.h>
#include<algorithm>
using namespace std;
int c[1010][1010];
int p[1010];
int n,cnt;
void Deal()
{cnt=0;for(int j=1;j<=n;j++)p[j]=j,printf("%d",p[j]),c[cnt][j]=p[j];int i=n-1;cnt++;while(1){while(i>0&&p[i+1]<p[i])i--;if(i==0)break;int j=n;for(;j>i;j--){if(p[j]>p[i])break;}swap(p[i],p[j]);for(i=i+1,j=n;i<=j;i++,j--)swap(p[i],p[j]);for(j=1;j<=n;j++){printf("%d",p[j]);c[cnt][j]=p[j];}printf("\n");cnt++;i=n-1;}
}
int main()
{while(scanf("%d",&n)!=EOF){Deal();}return 0;
}

2.递归法

长的排列可以通过固定一部分化归成短的排列

既然有了递推关系,就可以通过递归实现了。

#include<stdio.h>
#include<algorithm>
using namespace std;
int c[1010][1010];
int p[1010];
int cnt=0;
int n;
void Deal(int k)
{if(k==n){for(int i=1;i<=n;i++){printf("%d",p[i]);c[cnt][i]=p[i];}cnt++;printf("\n");return;}sort(p+k,p+n+1);for(int i=k;i<=n;i++){swap(p[i],p[k]);Deal(k+1);swap(p[i],p[k]);}
}
int main()
{while(scanf("%d",&n)!=EOF){cnt=0;for(int i=1;i<=n;i++)p[i]=i;Deal(1);}return 0;
}


第二类:按非字典序生成


1.邻位交换法

n个元素的排列与n-1个元素的排列有关,因为如果我们已知n-1个元素的排列情况,可以通过不断插入第n 个元素生成n个元素的排列。即(n-1)!*n=n!

比如:1 2 3    1 3 2  3 1 2

2 1 3   2 3 1   3 2 1

#include<stdio.h>
#include<algorithm>
using namespace std;
int n,cnt;
int c[1010][1010];
int p[1010];
void Copy()
{printf("cnt:%d ",cnt);for(int i=1;i<=n;i++)c[cnt][i]=p[i],printf("%d",p[i]);printf("\n");cnt++;
}
void Deal()
{cnt=0;int num=2;for(int i=3;i<n;i++){num*=i;}for(int i=1;i<=n;i++)p[i]=i;num/=2;while(num--)//S型插入{for(int i=n;i>1;i--){swap(p[i],p[i-1]);Copy();}swap(p[n],p[n-1]);Copy();//生成新的n-1排列for(int i=1;i<n;i++){swap(p[i],p[i+1]);Copy();}swap(p[1],p[2]);Copy();//生成新的n-1排列}
}
int main()
{while(scanf("%d",&n)!=EOF){Deal();}return 0;
}

2.逆序列倒推

由于每一个逆序列都确定唯一原数列。逆序列较原序列好枚举。所以通过逆序列倒退原数列。

设逆序列p1,p2,...,pn

0<=p1<=n-1,0<=p2<=n-2,...0<=pn-1<=1,pn=0;

p1,p2,...,pn 可以通过模拟n位(n-i)进制的方法枚举出逆序列。

#include<stdio.h>
int n,cnt=0;
int c[1010][1010];
int p[1010];
int s[1010];
void cal()
{for(int i=1;i<=n;i++){int num=0;for(int j=1;j<=n;j++){if(c[cnt][j]==0)num++;if(p[i]+1==num){c[cnt][j]=i;break;}}}for(int i=1;i<=n;i++)printf("%d",c[cnt][i]);printf(" ");for(int i=1;i<=n;i++)printf("%d",p[i]);printf("\n");cnt++;
}
void Deal()
{s[n-1]=1;cnt=0;for(int i=1;i<=n;i++){ c[cnt][i]=i;printf("%d",i);}cnt++;printf("\n");while(1){p[n]=0;for(int i=n-1;i>=1;i--){p[i]+=s[i];if(p[i]>n-i){p[i-1]++;p[i]-=n-i+1;}}if(p[0]==1)break;cal();}}
int main()
{while(scanf("%d",&n)!=EOF){Deal();}return 0;
}


2.由逆序列构建原排列


前面有些许涉及,这里再详细说下。

设逆序列为b1,b2,....,bn.所对应原排列为a1,a2,...,an

设置n个空位。

从1开始放。

由于1前面至少有b1个数,所以a1前至少有b1个空位。因为1之前没有放数,所以1放在a[b1]+1处.空位为 a_1~a_b1.

下面放2.

同样,2前面至少有b2个数,因为这b2个数全部大于2,还没有放进排列,所以2前要有把b2个空位(比2小的 已经放进排列中了。)。2放在第b2+1个空位处。

……

下面放k。

k前面至少有bk个数,k放在第bk+1个空位处(比k小的已经放进排列了)。

剩下的空位为n-k+1。bk的取值范围为0<=bk<=n-k,1<=bk+1<=n-k+1.所以一定放的下。

#include<stdio.h>
int b[10010],a[10010];
int main()
{int n;while(scanf("%d",&n)!=EOF){for(int i=0;i<n;i++)scanf("%d",&b[i]);for(int i=0;i<n;i++){int cnt=0;for(int j=0;j<n;j++){if(a[j]==0)cnt++;if(cnt==b[i]+1){a[j]=i+1;break;}}}for(int i=0;i<n-1;i++)printf("%d ",a[i]);printf("%d\n",a[n-1]);}
}

排列组合之生成排列_(:з」∠)_相关推荐

  1. 每日一题吧算是,见证自己的成长路程_(:з」∠)_

    目录 前言: 一.整理思路: 1.照明范围: 2.明亮空地的数组思想转化: 2.1: 2.2: 二.代码的实现和细节讲解: 1.变量的定义和含义: 2.火把照明的实现: 3.萤石照明的实现 : 4.对 ...

  2. 冒泡排序代码及其思路(怕忘记才记录的_(:з」∠)_)

    代码 System.out.println("输入5个数字进行从大到小(小到大)排列:");int[] nums = new int[5];for (int i = 0; i &l ...

  3. CodeForces Canada Cup 2016 A、B水题 _(:з」∠)_

    哭哭哭哭哭哭哭 又降了4...... 这次吸取的教训是...本来就是个做题慢的傻逼....一定要准时题目一开就开始做.....不然就等着降名次吧,..... 开始四十多分钟才开进去的.....再给我四 ...

  4. 清单革命 <<读后感>> _(:з」∠)_

    Q: 怎样能够避免犯错,让自己持续.正确.安全地做好事情? A:先读一遍清单革命,做一下总结看看. 过年在家浅显的读了一遍,以下个人观点: 一:清单是什么? 执行清单:            简单的问 ...

  5. 同余问题之中国剩余定理 _(:з」∠)_

    1.中国剩余定理又指孙子定理.叙述如下: 令m1,-,mr两两互素, b1,-,br为整数, x≡b1(mod m1),x≡b2(mod m2)--x≡br(mod mr);有唯一正整数解x,其形式为 ...

  6. 围成一圈的排列组合问题_行测技巧:排列组合之“环形排列”问题

    原标题:行测技巧:排列组合之"环形排列"问题 在公考学习备考中排列组合一直是大家比较头疼的题目,很多同学在高中时就对这种题目望而却步,其实排列组合题目虽然比较难,但是这类题目却可以 ...

  7. python 排列组合_python 编写排列组合

    python在编写排列组合是会用到 itertools 模块 排列 import itertools mylist= list(itertools.permutations(['A','B','C', ...

  8. java 数组的排列组合_java数组排列组合问题汇总

    面试或笔试中,多次遇到以下4个关于排列组合的手撕算法,这里做个笔记,方法日后查阅: 1. 无重复元素的数组,求全排列: 2. 有重复元素的数组,求全排列: 3. 无重复元素的数组,求组合[子集]: 4 ...

  9. EXCEL 把几列排列组合列出所有排列组合情况的绿色工具

    对于如下问题: EXCEL 利用排列组合公式列出所有排列组合情况 在excel中如何实现第一列和第二列排列组合,输出到第三列 使用这个工具:http://www.excelfb.com/ 点击: 排列 ...

最新文章

  1. win7安装mysql-8.0.13-winx64
  2. 通过修改注册表提升SSD性能(Intel 5系列芯片组)
  3. 步步为营UML建模系列二、部署图(Deployment Diagram)
  4. uipath sequence传递参数_多孔材料测试及声学参数识别(中)_多孔材料声学参数正向识别...
  5. 鸟哥的Linux私房菜(基础篇)-第二章、 Linux 如何学习(二.2. 鸟哥的Linux苦难经验全都录)
  6. lintcode:二叉树的层次遍历
  7. [新思路]Online DVD Rental! 美国在线DVD租赁
  8. win7 更新失败解决方案一
  9. 对比AppScan Source和Fortify扫描AltoroJ的结果
  10. oracle恢复被覆盖的存储过程
  11. js高级学习笔记-14-从函数运行和内存角度理解闭包
  12. Fanvas, 把swf文件转html5 canvas js软件工具程序
  13. p5.js之Q版人物绘制
  14. Laravel5.8调试消息队列RabbitMQ
  15. Spring事务管理A方法内部调用B方法的回滚问题(springboot事务管理)
  16. Blizzard的MPQ文件格式搜索算法
  17. Spring Security 集成 OIDC 项目编码 | 认证(三)
  18. postgresql 结束进程
  19. 百度地图点击地点显示经纬度并且转换为百度地址及添加控件
  20. 用selenium爬取csdn博客文章,并用4种方法提取数据

热门文章

  1. android lcd 显示图片,Android开发中通过AIDL文件中的方法打开钱箱,显示LCD屏幕
  2. 再编写代码中报错:CS8107 C# 7.0 中不支持功能“xxxxxx”。请使用 7.1 或更高的语言版本。...
  3. adb install 安装错误常见列表
  4. linux系统安装geany文本编辑器
  5. Hadoop3.X环境配置
  6. 如何快速判断一个文件是否为病毒
  7. python干货分享/网址总结
  8. 测试环境Hosts设置
  9. 极路由 支持php,目前极路由4增强版(B70)可用的最新固件整理!Padavan_PandoraBox_灯大_hanwckf_H大...
  10. 极路由 刷linux,记一次 极路由1S HC5661 TTL root 刷 U-BOOT 不死固件 及 爱快固件-20200320更新...