【蓝桥杯选拔赛真题14】C++正整数组合 青少年组蓝桥杯C++选拔赛真题 STEMA比赛真题解析

目录

C/C++正整数组合

一、题目要求

1、编程实现

2、输入输出

二、算法分析

三、程序编写

四、程序说明

1、主函数流程

2、dfs 函数流程:

五、运行结果

六、考点分析


C/C++正整数组合

第十二届青少组蓝桥杯C++选拔赛真题

一、题目要求

1、编程实现

输入两个正整数 n 和 m(20 >= m >= n > 0),n 代表正整数的个数,要求 n 个正整数相加的和为 m,输出满足这个条件的正整数组合有多少。

例如:当 n=4,m=8 时,满足条件的有 5 组(也就是:5+1+1+1=8,4+2+1+1=8,3+3+1+1=8,3+2+2+1=8,2+2+2+2=8,每组组合都由 4 个正整数组成且 4 个正整数的和等于 8)

2、输入输出

输入描述:分行输入 n 和 m(20>=m>=n>0)

输出描述:只有一行,一个整数,即输出满足这个条件的正整数组合有多少

输入样例:

4
8

输出样例:

5

二、算法分析

  1. 本题相对而言还是有一定难度的,这是一个比较典型的求某一个和值有多少种组合
  2. 碰到这种题目最好的解决方案就是采用深度优先的算法,然后使用递归回溯的方式求解
  3. 题目要求有n个数,可以将这n个数字进行递归,满足条件的进行统计,不满足回溯,然后进行这个位置的下一个数字,依次遍历完整个数字,这里要遍历的数字跟和值和前面数字求和的差值有关
  4. 所以最好的方式是定义一个自定义函数用来递归回溯
  5. 在调用函数之前先定义一个大一点的一维数组,用来保存每一种可能的组合,在调用自定义递归回溯函数之前需要先将数组的第一个数字设为1;同时在定义递归函数的时候需要设定退出递归函数的条件为:当前个数超过了输入的个数n,然后判断一下求和结果是否等于输入的m,如果是个数累加
  6. 最后输出统计个数即可

三、程序编写

#include 
using namespace std;
int n, m, sum = 0, count = 0;
int a[30];

//深度优先算法 递归回溯
void dfs(int k)
{
    if (k > n)
    {
        if (sum == m)
        {
            count++;
        }
        return;
    }
    for (int i = a[k - 1]; i <= m - sum; i++)
    {
        sum += i;
        a[k] = i;
        dfs(k + 1);
        sum -= i;
        a[k] = 0;
    }
}

int main()
{
    cin >> n >> m;
    a[0] = 1;
    dfs(1);
    cout << count << endl;
    return 0;
}

四、程序说明

1、主函数流程

  1. 首先需要导入输入输出流头文件
  2. 然后是引入std命名空间中的所有成员到当前的程序中,这样在当前的程序中就可以直接使用 std 命名空间中的所有成员,而不需要使用的时候在成员前面加上(std::)前缀
  3. 接着声明程序的入口,也就是主函数(主函数在一个程序中只允许出现一次)
  4. 根据题目要求声明4个全局变量(n组合数的个数,m相加的和,sum已有组合数字的和,count统计符合条件的个数),同时声明一个整形一维数组
  5. 然后利用输入流对象cin,从键盘读取这2个变量的值
  6. 将数组的第一个元素设置为1
  7. 调用自定义函数dfs(1)
  8. 最后利用输出流对象cout,结合fixed和setprecision函数按要求输出双精度浮点数保留小数位数和另一个整数
  9. 最后返回0,程序结束

2、dfs 函数流程:

  1. 如果 k 大于 n(也就是已经选取了 n 个数字),则检查 sum 是否等于 m,如果等于则统计变量count加1。
  2. 利用for语句对数组 a 的当前位置 k-1 到最后一个位置(也就是最后一个数字,m-sum),执行以下循环:
    a. 把数组a当前位置 k 的元素设为 i
    b. 把 i 加到 sum 上。
    c. 把 i 存到数组 a 的当前位置 k
    d. 递归调用 dfs(k+1),也就是到下一层(下一个加数)继续搜索。
    e. 在返回上一层之前,从 sum 中减去 i(回溯),并且把数组 a 的当前位置设为0(回溯)。
  3. 返回主函数,输出 count

五、运行结果

4
8

5

六、考点分析

难度级别:难,这题相对而言有一定难度,具体主要考查如下:

  1. 学会题目分析,算法分析,复杂问题模块化,简单化,从中找到相应的解题思路
  2. 充分掌握变量的定义和使用
  3. 学会深度优先算法的机制和应用
  4. 学会递归函数和回溯函数的机制和使用
  5. 学会输入流对象cin的使用,从键盘读入相应的数据
  6. 学会for循环的使用,在确定循环次数的时候推荐使用学会
  7. 学会if条件判断语句的使用,满足一定条件才能执行后面的语句
  8. 掌握输出流对象cout的使用,与流插入运算符 << 结合使用将对象输出到终端显示
  9. 充分掌握变量定义和使用、递归回溯函数、循环语句和深度优先算法知识的使用及输入输出的用法

PS:方式方法有多种,小朋友们只要能够达到题目要求即可!

你可能感兴趣的:(蓝桥杯C++选拔赛真题详解,C++蓝桥杯真题,蓝桥杯C++真题,C++蓝桥杯选拔赛真题,C++深度优先算法,C++递归函数,C++正整数组合,C++递归回溯)