蓝桥杯 第三课 排列组合与递归


排列问题 = 排列计数 + 排列枚举

  • 第一个例子 “abcd” 的全排列?(字符串的全排列)

//采用依次插空排序的方法 
#include<iostream> 
#include<string>
using namespace std;
int calc(string p,int k)  //将排列好的数据存储在 p 中,k代表下标移动的值 
{
     if(k== p.length()-1)
     {
        cout<<p<<endl;
        return 0;
     }
     char temp;
     for(int i= k;i<p.length();i++)
     {
        temp = p[k];
        p[k] = p[i];
        p[i]  = temp;//首先进行交换 

        calc(p,k+1); // 然后进行递归 


        temp = p[k];//然后回溯  保证字符串出该层循环的时候还是原来的字符串 
        p[k] = p[i];
        p[i]  = temp;

     }   
     return 0;       
}
int main()

{
    string s = "asd";
    calc(s,0);
    return 0; 
}

这里有个问题,插空的时候,为什么直接让 i = k 呢?为什么只向后进行排列而不与前面进行排列呢?
这里写图片描述

因为 k 是不断从前往后的,所以第k个元素一定与其后的所有元素进行过交换了。
所以下一个元素不必再与前一个元素进行交换。

  • 第二个例子
小明最近喜欢搭数字积木。一共有10块积木,每个积木上有一个数字,0~9。

搭积木规则:
每个积木放到其它两个积木的上面,并且一定比下面的两个积木数字小。
最后搭成4层的金字塔形,必须用完所有的积木。

下面是两种合格的搭法:

   0
  1 2
 3 4 5
6 7 8 9

   0
  3 1
 7 5 2
9 8 6 4    

请你计算这样的搭法一共有多少种?

思路 : 暴力枚举 (全排列 条件判断)

可以转化成一维的,题目转换为 对0-9 进行全排列。


组合问题 = 组合计数 + 组合枚举

组合计数

  • 问题1 m个 中 取n 个,有多少种取法?
 递归公式   f(m,n) = f(m-1,n-1) + f(m-1,n-1)
 假设 m 中有一个特殊,若这个没取  ,为(m-1,n)
                   若这个取了  ,为(m-1,n-1)
#include<iostream> 
using namespace std;
int calc(int m, int n)//m个球中取 n 个 
{
    if (m<n)return 0;
    if (n == 0)return 1;
    if (m == n)return 1;
    return calc(m - 1, n - 1) + calc(m - 1, n);
}
int main()
{
    int s = calc(3, 2);
    cout << s << endl;
}
  • 问题二

    若有重复元素
    例如 问题:AAABBCCCCDD 中取3个,所有取法?

    可以全排进行筛选


实际应用

X星球要派出一个5人组成的观察团前往W星。
其中:
A国最多可以派出4人。
B国最多可以派出2人。
C国最多可以派出2人。
D国最多可以派出1人。
E国最多可以派出1人。
F国最多可以派出3人。
那么最终派往W星的观察团会有多少种国别的不同组合呢?

与上题类似


计数枚举的框架
这里写图片描述


问题

这里写图片描述

这里写图片描述

这里写图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值