递归实现组合数和排列数的区别

递归实现排列型枚举
递归实现组合型枚举
大家仔细看上面的两道题区别是不是很熟悉呢,没错,这就是我们排列组合的问题,接下来,我们就要用递归分别实现这两个
第一个:递归实现排列型枚举

#include 
#include 
#include 
#include 

using namespace std;

const int N = 10;

int n;
int state[N];   // 0 表示还没放数,1~n表示放了哪个数
bool used[N];   // true表示用过,false表示还未用过

void dfs(int u)
{
    if (u > n)  // 边界
    {
        for (int i = 1; i <= n; i ++ ) printf("%d ", state[i]); // 打印方案
        puts("");

        return;
    }

    // 依次枚举每个分支,即当前位置可以填哪些数
    for (int i = 1; i <= n; i ++ )
        if (!used[i])
        {
            state[u] = i;
            used[i] = true;
            dfs(u + 1);

            // 恢复现场
            state[u] = 0;
            used[i] = false;
        }
}

int main()
{
    scanf("%d", &n);

    dfs(1);

    return 0;
}

//作者:yxc
//链接:https://www.acwing.com/activity/content/code/content/156257/
//来源:AcWing
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

这是来自Y神的代码,下一题,就跟这个代码有区别了

第二题:递归实现组合型枚举

众所周知,排列是有顺序的,组合是没顺序的,那么,怎么才能让有顺序的变成没有顺序的呢,这就需要我们人为的给它规定一个顺序,比如,我要求只能按照字典序从小到大的顺序,那么就不会输出其他顺序的情况
那么,如何限制它是从小到大呢,我们只需要保证,相邻的两个数,前边的是小于后边的就可以
即,只需要保证每次新加的数小于前面的那个数

开始枚举,依次枚举每个位置上的数是几。
递归实现组合数和排列数的区别_第1张图片
(时间复杂度在一个亿以内都是可以的)

#include 
#include 
#include 
#include 

using namespace std;

const int N = 30;

int n, m;
int way[N];

void dfs(int u, int start)//u表示现在枚举的位置,start表示该从哪个数开始枚举
{
    if (u + n - start < m) return;  // 剪枝
    if (u == m + 1)
    {
        for (int i = 1; i <= m; i ++ ) printf("%d ", way[i]);
        puts("");
        return;
    }

    for (int i = start; i <= n; i ++ )
    {
        way[u] = i;
        dfs(u + 1, i + 1);
        way[u] = 0; // 恢复现场
    }
}

int main()
{
    scanf("%d%d", &n, &m);

    dfs(1, 1);

    return 0;
}

//作者:yxc
//链接:https://www.acwing.com/activity/content/code/content/159566/
//来源:AcWing
//著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(#,蓝桥杯,c语言,数据结构)