排列组合问题

排列组合问题

​ 排列组合是组合数学里的两大经典问题,下面我们先来看一下它的定义:

排列:从n个不同元素中任取m(m≤n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列。

组合:一般地,从n个不同的元素中,任取m(m≤n)个元素为一组,(即不考虑顺序),叫作从n个不同元素中取出m个元素的一个组合

一、全排列问题

​ 首先我们可以先简化一下这个问题,就令 n = m n=m n=m,我们可以讨论一下做法。

​ 这个问题很容易看出,我们可以简单粗暴的用dfs暴力求解,当需要排列的数字为n时,时间复杂度明显是 O ( 2 n ) O(2^{n}) O(2n),效率有点低吧,不过应该不能优化了。其中b数组用于判重。

代码如下(只有P的老师别打我):

procedure try(x:longint);
var
  i:longint;
begin
  if x>m then
  begin
    print;
    exit;
  end;
  for i:=1 to n do
    if not b[i] then
    begin
      a[x]:=i;
      b[i]:=not b[i];
      try(x+1);
      b[i]:=not b[i];
    end;
end;

​ 在这里安利一波stl库的做法(STL大法好),我们可以用下面这个代码来求解n个元素的全排列问题:

cin >> a;
sort(a,a+n);
int ans=0;
do{
   
    puts(a);
    ans++;
}while(next_permutation(a,a+n));
cout << ans;

​ 那么这个东西捏,也就是next_permutation这个函数(划重点),它存在于c++的algorithm库中,用途是求a数组的下一个字典序排列,还有个bool类型的返回值,可以直接用于循环的判断。

​ 那么我们现在来看一下全排列问题当 n ≤ m n\leq m nm时,我们又应该怎么办呢?

​ 在我们的dfs程序里只要将输出的判断参数n改成m就行了好白痴啊233。时间复杂度$O(n^{m}) $.

二、全组合问题

​ 明显我们可以看出,这个问题相类似与全排列问题,不过需要判断重复而已。那么其实也很容易想到,我们只需要从前往后搜,不回头就一定不会出现重复的组合并且它一定是按字典序排列的。所以我们可以在我们的dfs中增加一个参数,每次记录下当前搜到的位置,传到下一层就从这个位置的后一位继续搜。

​ 时间复杂度,emmm,好像很难算的样子,应该可以用组合公式求出,就先卖一个关子。

​ 在luogu上还有这样子的玄学做法:将一个数组x的m项赋值为0,其它赋值为1,先从小到大排序,就可以通过上面那一个next_permutation这个函数来求每一个x数组的每一个排列。在每一个排列中,我们可以输出x数组中值为0的项。复杂度 O ( n m ⋅ m ) O(n^{m}·m) O(nmm).

​ 代码。。给一下吧:

for(int i=r+1;i<=n;++i)
        x[i]=1; 
    do{
   
        for
  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值