排列组合问题相关知识

排列组合问题

这篇随笔讲解信息学奥林匹克竞赛比较常见的一种题型——排列组合问题。阅读并理解本篇随笔要求读者具有不低于高中一年级的数学素养,并且了解信息学中递归、深搜算法的基本实现方式,能理解一般的递归程序。

上课!!

1、排列和组合的定义

(1)排列的定义

\(n\)个不同元素中,选出\(m\)个元素按照一定顺序排成一列,叫做从\(n\)个不同元素中取出\(m\)个元素的一个排列。

(2)排列数的定义

\(n\)个元素中选出\(m\)个元素的所有排列的个数,叫做从\(n\)个不同元素中取出\(m\)个元素的排列数。

(3)全排列的定义

\(n=m\)时所有的排列情况叫做全排列

(4)组合的定义

\(n\)个不同元素中,选出\(m\)个元素并成一组,叫做从\(n\)个不同元素中取出\(m\)个元素的一个组合。

(5)组合数的定义

\(n\)个元素中选出\(m\)个元素的所有组合的个数,叫做从\(n\)个不同元素中取出\(m\)个元素的组合数。

(6)排列&组合的区别

通俗地说,组合不分顺序,而排列分顺序,也就是说,对于数列\(1,2\),有以下两种排列:\(1,2\)\(2,1\),但是仅有一种组合\(1,2\)\(2,1\).

2、排列&组合的公式

(1)关于排列的公式

\(n\)个不同元素中,选出\(m\)个元素的排列数,数学表示为:\(A_n^m\).

计算公式如下:

\[A_n^m=n(n-1)(n-2)\cdots(n-m+1)=\frac{n!}{(n-m)!} \]

(2)关于组合的公式

\(n\)个不同元素中,选出\(m\)个元素的组合数,数学表示为:\(C_n^m\).

计算公式如下:

\[C_n^m=\frac{A_n^m}{m!}=\frac{n!}{m!(n-m)!} \]

(3)关于全排列的公式

某个数列的全排列数\(f(n)\),计算公式如下:

\[f(n)=n! \]

3、全排列的求法

例题:生成全排列(深搜基础题)

题目链接

给定\(n\),生成\(1-n\)的全排列。

我们考虑用递归来解决全排列问题:

递归出口是当x==n+1地时候,绝对不能仅仅等于n!!

我们的递归部分使用标记数组和数列数组实现,具体实现方法可以参照下图:

我们递归的过程大体是以下的思路:

三个数位可能出现1-3每个数,所以我们使用递归算法求解的时候,先圈定这一个值,然后继续下搜,遍历完这“一条链”的时候,就上回一个数位看看还有没有其他选择,这样就保证了解不重不漏。

例题代码:

#include<bits/stdc++.h>
using namespace std;
int n,a[20],v[20];
void dfs(int x)
{
    if(x==n+1)
    {
        for(int i=1;i<n;i++)
            printf("%d ",a[i]);
        printf("%d\n",a[n]);
        return;
    }
    for(int i=1;i<=n;i++)
    {
        if(v[i]==0)
        {
            a[x]=i;
            v[i]=1;
            dfs(x+1);
            v[i]=0;
        }
    }
}
int main()
{
    scanf("%d",&n);
    dfs(1);
    return 0;
}
posted @ 2019-08-15 15:02  Seaway-Fu  阅读(7783)  评论(0编辑  收藏  举报