vijosP1092 全排列

链接:https://vijos.org/p/1092

【思路】

数学+搜索。

根据序号依次确定每一个数。

首先我们可以把未选的数看作一个可选择集合,其次把寻找过程看作一棵树上的操作,如果有n个数我们已经确定了d个数,那么无论第d+1个数为多少以当前可选择集合中的任意一个数为根的子树的大小为(n-d-1)! 由此我们可以根据序号继续搜索。

注意:选择k的含义为选择了当前可选择集合中第k小的数。

详见代码

【代码】

 1 #include<iostream>
 2 #include<cstdlib>
 3 using namespace std;
 4
 5 typedef long long LL;
 6 int n;
 7 LL m;
 8 int A[25];
 9 int vis[25];
10
11 void dfs(int d,LL num) {
12     if(d==n) {
13         for(int i=0;i<d;i++) cout<<A[i]<<" ";
14         exit(0);
15     }
16     LL tmp=1;
17     for(int i=1;i<=(n-d-1);i++) tmp *= i;
18     for(int k=1;k<=n;k++)
19       if((k-1)*tmp<=num && num<=k*tmp) {
20           int cnt=0; int i;
21           for(i=1;i<=n;i++) if(!vis[i]) if(++cnt==k) break;
22           vis[i]=1; A[d]=i;
23           dfs(d+1,num-(k-1)*tmp);
24       }
25 }
26
27 int main() {
28     cin>>n>>m;
29     dfs(0,m);
30     return 0;
31 } 

注:本题与紫书P323 Password一题类似。

时间: 2024-08-08 23:56:58

vijosP1092 全排列的相关文章

生成n个元素的全排列 C实现

近期在准备复习算法设计的考试,下边记录一些,看笔记时突然想到的解法. 问题是这种 用递归实现 n 个元素的全排列. 当时老师给出的解答是 假定第i个元素 ri 放在首位,于是 f(r1,r2,-,rn) = f(ri U {r1, r2,-.,rn}) = U (ri & f(r1,r2, -, rn)), 当时应该是听懂了,只是如今看到这个笔记.又醉了. (这货竟然是我上课记的笔记 .... . .. .) 后来自己细致想想,事实上非常简单的 一个问题, 利用回溯法,把问题看成是一个排列树.能

递归实现全排列(一)

[思路] 下面用具体例子来阐述这种实现的思路,例如实现123的全排列组合. 要求123的全排列,可以分为以下情况: 情况1:第0位为1+23的全排列 情况2:第0位为2+13的全排列 情况3:第0位为3+32的全排列 上面的情况用代码实现如下: //情况1 //为了跟下面一致,加上swap(list[0],list[0]); perm(list,1,2); //为了跟下面一致,加上swap(list[0],list[0]); //情况2 swap(list[0],list[1]); perm(l

全排列算法-Java

第一步,排列的精髓是交换和顺序处理,比如,考虑[1,2,3,4]排列,实际上是,1和1,2,3,4分别交换得来 1和1交换:[1],[2,3,4] 1和2交换:[2],[1,3,4] 1和3交换:[3],[2,1,4] 1和4交换:[4],[2,3,1] 那么下面分别考虑上面的四个结果,比如,考虑 [1],[2,3,4] 第二步,我们把[1]固定不变,考虑[2,3,4],把它看成是2和2,3,4分别交换,得到如下结果: [1]固定,2和2交换:[1],[2],[3,4] [1]固定,2和3交换:

求数字或者字符串的全排列

以数字举例:有一个数组A的数为 :1 2 3 4 ,其按字典序列的全排列为: 1 2 3 4 1 3 2 4 1 3 4 2 1 4 2 3 1 4 3 2 2 1 3 4 2 1 4 3 2 3 4 1 ---. 总共有 n!个排列,现在输入一个数K,输出其第K的排列 方法:采用康托编码的思想,其实就是求出每个位置上的数字:第一个位置的数字,第二个位置的数字.... 解法:按顺序求出每个位置上的数,这边假设 K=8 :数组为:1 2 3 4 ,长度为4,位置p代表数组中第P个数:p=k/ (n

递归算法:求序列的全排列

用C++模板书写一段序列数组的全部排列 /** * 书本:[windows程序设计] * 功能:输出全部的排列情况 * 文件:全排列.cpp * 时间:2014年9月29日21:52:55 * 作者:cutter_point */ #include <iostream> using namespace std; //交换两个元素的函数 template<class Type> inline void Swap(Type &a, Type &b) //取两个元素的引用

深度优先排序(数字全排列)

输入一个整数n(n<10),输出1-n的全排列 1 import java.util.Scanner; 2 public class One { 3 //数组a(模拟放数字牌的盒子)用于存放排序数字,数组book[i]用于标记牌i是否已经放入数组a 4 public static int a[]=new int[10],book[]=new int[10],n; 5 //函数f()用于输出所有可能情况的排列. 6 public static void f(int x){//x为第几个盒子 7 i

全排列问题的递归算法(Perm)

[题目]设计一个递归算法生成n个元素{r1,r2,-,rn}的全排列. [算法讲解] 设R={r1,r2,-,rn}是要进行排列的n个元素,Ri=R-{ri}.集合X中元素的全排列记为perm(X).(ri)perm(X)表示在全排列perm(X)的每一个排列前加上前缀得到的排列.R的全排列可归纳定义如下: 当n=1时,perm(R)=(r),其中r是集合R中唯一的元素:当n>1时,perm(R)由(r1)perm(R1),(r2)perm(R2),-,(rn)perm(Rn)构成.实现思想:将

POJ - 2718 Smallest Difference(全排列)

题意:将n个数字分成两组,两组分别组成一个数字,问两个数字的最小差值.要求,当组内数字个数多于1个时,组成的数字不允许有前导0.(2<=n<=10,每个数字范围是0~9) 分析: 1.枚举n个数字的全排列. 2.当两组数字个数相同或只差1时组成的两个数字才可能出现最小差值. 3.0~cnt/2 - 1为前半组数字,cnt/2~cnt-1为后半组数字. 4.注意getchar()的位置. #pragma comment(linker, "/STACK:102400000, 102400

全排列问题(JAVA和Python实现)

问题:给定指定字符串(ABCCEF)输出其全排列.   运用分治的思想 JAVA:用TreeSet去重(且保持有序) import java.util.Set; import java.util.TreeSet; public class Main { static Set<String> result=new TreeSet<String>();//用来去掉重复的元素 public static void fullPermutation(char[] data, int flag