排列组合问题相关知识
排列组合问题
这篇随笔讲解信息学奥林匹克竞赛比较常见的一种题型——排列组合问题。阅读并理解本篇随笔要求读者具有不低于高中一年级的数学素养,并且了解信息学中递归、深搜算法的基本实现方式,能理解一般的递归程序。
上课!!
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\).
计算公式如下:
(2)关于组合的公式
从\(n\)个不同元素中,选出\(m\)个元素的组合数,数学表示为:\(C_n^m\).
计算公式如下:
(3)关于全排列的公式
某个数列的全排列数\(f(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;
}