C++ 全排列问题——递归枚举法

全排列问题是一道非常经典的递归题目,而递归枚举法求解也是最暴力的一种方法。

例题

洛谷1706

题目描述
输出自然数1到n所有不重复的排列,即n的全排列,要求所产生的任一数字序列中不允许出现重复的数字。

输入格式
一个整数n。

输出格式
由1~n组成的所有不重复的数字序列,每行一个序列。
每个数字保留 5个场宽。

输入样例

3

输出样例

    1    2    3
    1    3    2
    2    1    3
    2    3    1
    3    1    2
    3    2    1

全排列问题——递归枚举法

这是一道经典的递归的题,每次递归枚举第x个数字是几,就是从1到n枚举一个遍,如果说当前数字还未被使用(flag[x]为false),就让a[x] = i,并将i标记为使用过(flag[x] = true)。如果dfs到第(n + 1)了就输出a数组,之后返回就行了。

简而言之,就是每到一位我就选一个尚未被使用过的数字。

这里我们可以算一下由1~n组成的全排列的数量:第一位我们可以从1 ~ n中任选一个数,之后到第二位我们发现除了第一位的数a[1]不能选还能选(n - 1)个数,再到第三位我们发现除了第一位和第二位的数a[1]、a[2]不能选还能选(n - 2)个数……到第n位我们发现只剩下一种选择方法。所以利用数学上排列组合中的乘法原理可以算出由1~n组成的全排列有n!个。

最后,算一下时间复杂度,我们发现需要从1到n一位一位的看,之后每位还要枚举1 ~ n,所以总时间复杂度为O(n^n^)。

代码

# include <cstdio>
# include <cmath>
# include <cstring>
# include <algorithm>

using namespace std;

const int N_MAX = 10;

int n;
int a[N_MAX + 10];
bool flag[N_MAX + 10];

void permutation(int x)
{
    if (x > n) {
        for (int i = 1; i <= n; i++)
            printf("%5d", a[i]);
        printf("\n");
        return;
    }
    for (int i = 1; i <= n; i++) {
        if (flag[i]) continue;
        a[x] = i;
        flag[i] = true;
        permutation(x + 1);
        flag[i] = false;
    }
}

int main()
{
    scanf("%d", &n);
    permutation(1);
    return 0;
}

原文地址:https://www.cnblogs.com/000zwx000/p/12335163.html

时间: 2024-08-01 20:10:02

C++ 全排列问题——递归枚举法的相关文章

C++ 全排列问题——递归交换法

对于求解全排列问题有最暴力的递归枚举法,但是我们希望可以优化时间,因此出现了递归交换法. 例题 洛谷1706 题目描述 输出自然数1到n所有不重复的排列,即n的全排列,要求所产生的任一数字序列中不允许出现重复的数字. 输入格式 一个整数n. 输出格式 由1-n组成的所有不重复的数字序列,每行一个序列. 每个数字保留 5个场宽. 输入样例 3 输出样例 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1 全排列问题--递归交换法 其实跟暴力枚举思路差不多,每次递归枚举第x个数字

for循环枚举法,全排列+dfs,补充浮点数注意事项

其实这个题目我一直没想好应该叫什么,就是在做蓝桥杯的时候会遇到很多的题,给你一等式,abcdef...分别是1-9(||12||15)不重复问你有几种方案? 我之前一直都是用的for循环在做,听说这叫什么暴力破解还是枚举法的.小白不是很懂这些. 但是之前做过一道题,好像就是15个数的for循环写的,一个是巨累(因为我用a!=b&&a!=c&&a!=....真的特别多而且容易写错),另一个是我记得我这道题写了很久最后提交没有分数,因为!!!超时了!!! 真的特别气,当时的我只

八皇后问题(回溯法&amp;枚举法)

作者 : 卿笃军 本文讨论了八皇后问题的三种解决方案: 一.枚举法 二.回溯法(递归版) 三.回溯法(非递归版) 本来这些代码是以前编写好的,没有发表,由于最近又学习到了八皇后问题,自己整理了一下发表了出来! 首先.说明一下何为八皇后问题,我也不去谷歌了,直接简单的说明一下: 八皇后问题,就是在一个8*8的平面棋盘上,要求你摆放8个棋子,要求:这8个棋子不能有2个在同一行,也不能有2个在同一列,同时一条斜线上面也不能有2个~~~~ 比如:4*4的棋盘,你可以这样摆放(4皇后问题): 以上图为参照

回溯枚举法

         回溯法也称试探法,它可以系统的搜索一个问题的所有解或者任意解.          回溯法是一个既带有系统性又带有跳跃性的的搜索算法.它在包含问题的所有解的解空间树中,按照深度优先的策略,从根结点 出发搜索解空间树.算法搜索至解空间树的任一结点时,总是先判断该结点是否肯定不包含问题的解.如果肯定不包含,则跳过 对以该结点为根的子树的系统搜索,逐层向其祖先结点回溯.否则,进入该子树,继续按深度优先的策略进行搜索.回溯法在用来 求问题的所有解时,要回溯到根,且根结点的所有子树都已被搜

枚举法判断某天是否为2015年节假日或周末

枚举法判断某天是否为2015年节假日或周末 1.节假日枚举类 /** *功能说明:节假日枚举类 * *创建人:Gansuper * *创建时间:2015-2-6 上午10:32:17 * *修改人 修改时间 修改描述 * */ public enum HolidayEnum { HOLIDAY(new String[]{"2015-01-01","2015-01-02","2015-01-03", "2015-02-18",&

Swift枚举-相关值与递归枚举

代码: enum ArithmeticExpression { // 相关值 case Number(Int) // 递归枚举 indirect case Addition(ArithmeticExpression, ArithmeticExpression) indirect case Multiplication(ArithmeticExpression, ArithmeticExpression) indirect case Division(ArithmeticExpression, A

【算法学习笔记】28.枚举法 解题报告 SJTU_OJ 1255 1256 魔戒

1256. 你的魔戒?不,是你的魔戒.加强版 Description 在前往末日火山的途中,佛罗多与他的霍比特人同胞不幸被半兽人抓住了.半兽人要对每个霍比特人进行询问,以找出哪个霍比特人携带了至尊魔戒.每个霍比特人可能会说以下几种话: I have the ring. 我有魔戒. I have not the ring. 我没有魔戒. XXX has the ring. XXX有魔戒.(XXX表示某个霍比特人的名字) XXX has not the ring. XXX没有魔戒. Today is

枚举法的简单应用

箱子里有红,黄,蓝,白,黑五种颜色玻璃球若干,每次任意拿出三个球,问拿出三种不同颜色玻璃球的可能取法,请输出每种排列的情况. 注解:利用枚举法定义五种情况,“enum color {red,yellow,blue,white,black};”,定义四个整形变量“int i,j,k,m=0;”,依次从i到k分别进行从红到黑的情况循环,利用if来决断i,j,k互不相等的情况,针对每种情况通过调用函数来进行输出转换,得到结果. 编程: #include <iostream>using namespa

从全排列看递归

1.什么是递归 1)举个生活中的例子:假设有一项很繁重的工作,我们总能把它划分为:总工作量=今天的工作+剩下的工作,只要我们每天都在坚持,一点点继续,那么剩下的工作会越来越少,总有一天,我们可以实现我们的梦想!(程序员的自我安慰~) 2)数学上来看: 例如:n的阶乘 f(n) = n!,n为整数 f(n) = 1   n<= 1                       (1) n*f(n-1) n >1                  (2) 有一个基础部分:它包含一个或多个值,对这些值