CSP初赛复习-31-阅读程序-递归-分治算法

分治算法(Divide and Conquer)

分治算法(Divide and Conquer)是一种递归的问题解决方法,它将问题分解成更小的子问题,然后解决子问题并将它们的解合并起来得到原问题的解。具体步骤如下:

1 分解(Divide):将原问题划分为多个规模较小但类似于原问题的子问题。

2 解决(Conquer):递归地解决每个子问题。如果子问题足够小,无需再继续分解,可以直接求解。

3 合并(Combine):将子问题的解合并起来,得到原问题的解。

分治算法常用于解决问题的规模较大且可以分解成相互独立且较小的子问题的情况。

经典的应用包括归并排序、快速排序和求解最大子数组等。

通过将问题划分为更小的子问题并分别解决,分治算法可以提高问题解决的效率。然而,该算法并非适用于所有问题,因为分解和合并的开销可能会导致算法的效率降低。在选择使用分治算法时,需要仔细考虑问题的性质和规模。

如下为分治算法的应用

阅读程序 CSP-J 2019

01 #include <iostream>
02 using namespace std;
03 const int maxn = 10000;
04 int n;
05 int a[maxn];
06 int b[maxn];
   /*
     l为左端点 r为右端点
     depth为深度 
     可以分解为递归搜索树进行计算
   */
07 int f(int l, int r, int depth) {
08     if (l > r)//递归出口
09         return 0;
10     int min = maxn, mink;
11    for (int i = l; i <= r; ++i) {//树的每个子问题找最小值和最小值对应下标
12         if (min > a[i]) {
13             min = a[i];
14             mink = i;
15         }
16     }
17     int lres = f(l, mink - 1, depth + 1);//左半部分值
18     int rres = f(mink + 1, r, depth + 1);//右半部分值
19     return lres + rres + depth * b[mink];//左半部部分值+右半部分值+depth*b[mink]
20 }
21 int main() {
22     cin >> n;
23     for (int i = 0; i < n; ++i)
24         cin >> a[i];
25     for (int i = 0; i < n; ++i)
26         cin >> b[i];
27     cout << f(0, n - 1, 1) << endl;
28     return 0;
29 }

判断题

1 如果 a 数组有重复的数字,则程序运行时会发生错误。()

答案 F

mink是找到第一个最小的,即使重复对程序结果没有影响

2 如果b数组全为0,则输出为0 ()

答案 T

计算最基本的是 depth * b[mink],对这些结果相加 ,如果b数组全为0,depth * b[mink] 为0,最终结果也为0

选择题

3 当 n=100 时,最坏情况下,与第12 行的比较运算执行的次数最接近的是:()

A 5000
B 600
C 6
D 100

答案 A

最坏情况下,每次找到的都恰好是最前面的(也可以每次找到的都恰好是最后面的),看作树型结构的话,每层只有一个节点

总共100层,每次运算次数主要为for循环找最小数的次数,每过一层后就少一个节点

第1层 循环次数 100

第2层循环次数 99

第3层循环次数 98

...

第100层循环测试 1

所以执行次数为

100+99+98+...+1=5050

5050和5000最接近

4 当 n=100 时,最好情况下,与第 12 行的比较运算执行的次数最接近的是:()

A 100
B 6
C 5000
D 600

答案 D

最好的情况下,每次平均分成左右2部分,记作第1层

分成的左右2部分,每一部分再平均分成左右2部分,记作第2层

这样继续分下去,层数为logn

每次都比较n次,所以总数为n * logn

比较次数和600最接近

5 当 n=10 时,若 b 数组满足,对任意 0≤i<n,都有 b[i] = i + 1,那么输出最大为()

A 386
B 383
C 384
D 385

答案 D

b数组的值 1 2 3 4 5 6 7 8 9 10

每一层输出增加depth * b[mink],要使depth * b[mink]最大

需要层数越大越好

需要depth越大,对应的b[mink]越大

因此,depth从1开始,b[i]数组也从1开始

depth=1 b[0]=1

depth=2 b[1]=2

depth=3 b[2]=3

...

depth=10 b[10]=10

所以结果为1*1+2*2+3*3+...+10*10=385

6 (4分)当n=100 时,若 b 数组满足,对任意 0≤i<n,都有 b[i]=1,那么输出最小为()

A 582
B 580
C 579
D 581

答案 B

由于b数组都为1,要使输出最小,需要层数最小
因此构造每一层都是满的二叉树可使值最小
从第1层开始逐层计算对应结果
第1层 1*1
第2层 2*2
第3层 4*3
第4层 8*4
第5层 16*5
第6层 32*6
第7层 37*7  -10-63(1~6层的节点和)=37
最小值上面1~7层相加和为580
posted @ 2023-09-08 22:49  new-code  阅读(74)  评论(0)    收藏  举报