如果有什么问题欢迎一起讨论纠正~
由于是导出的个人感觉格式没有那么好,如需更好的阅读体验请看文章末尾
目录
1. 阐述回溯算法与分支限界算法的区别和联系,各自强调改善那方面以提高效率,各适合那些问题?
2. 采用动态规划算法必须满足的条件是什么?动态规划算法是通过什么问题的什么特性提高效率的?
3. 陈述算法在最坏情况下的时间复杂度和平均时间复杂度;这两种评估算法复杂性的方法各自有什么实际意义?
4. 比较贪心算法与动态规划算法的异同,它们都有那些优势和劣势?
1. 使用回溯法解0/1背包问题:n=3,C=50,V={60,100,120},W={10,20,30},要求用一棵完全二叉树表示其解空间。画出其解空间树,计算其最优值,并构造最优解
2. 使用分支限界解0/1背包问题:n=3,C=50,V={60,100,120},W={10,20,30},要求用一棵完全二叉树表示其解空间。画出其解空间树,计算其最优值,并构造最优解。
1. 把一个字符串(数组)进行逆序操作,如“abc"逆序为“cba” ,要求空间复杂度为O(1)
2. 请用递归算法实现判断一个数组是否是从小到大排序,要求递归函数返回bool值. 比如数组1,2,3,4,5,6是从小到大排序,递归函数返回true
4. 求一个数组的最长递减(上升)子序列比如{9,4,3,2,5,4,3,2}的最长递减子序列为 {9,5,4,3,2}
5. 请用递归算法实现判断一个字符串是否是对称字符串,要求递归函数返回bool值. 比如“abcdcba”是对称字符串,递归函数返回true
6. 请用递归算法求和,公式为:f(n)=2+4+6+.....+(2*n),n为正整数,f(n)不会超出整数范围。要求递归函数返回int类型
9. 键盘输入n个正整数(互不相等),找出其中和等于m的所有组合。
11. 编写函数double getRestul(int n),它的功能是:根据以下公式计算结果S
12. 有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛
13. 给定n个正整数wi和一个正整数m,在这n个正整数中找出一个子集,使得子集中的正整数之和等于m
14. 编写函数double getRestul(int n),它的功能是:根据以下公式计算结果S
16. 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法,并输出每种跳法具体怎么跳
17. 某公司拟将5百万元,向A、B、C三个项目追加投资,三个项目可以有不同的投资额度,相应的效益值如表所示,问如何分配资金,才使总效益值最大?下表是追加投资到各项目的额度收益表。
21. 高矮不同的12个人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?
一、填空题
- 算法的复杂性有时间复杂性和空间复杂性之分(P1)
- 程序是算法用某种程序设计语言的具体实现(P1)
- 算法的“确定性”指的是组成算法的每条指令是清晰的,无歧义的(P1)
- 回溯法中的解空间树结构通常有两种,分别是子集树和排列树(P124)
- 分治法的基本思想是首先将待求解问题分解成若干子问题(P16)
- 回溯法搜索解空间树时,常用的两种剪枝函数为约束函数和限界函数(P122)
- 动态规划算法的两个基本要素是最优子结构和重叠子问题(P51)
- 解决0/1背包问题可以使用动态规划、回溯法,其中不需要排序的是动态规划,需要排序的是回溯法
- 10000*n2+10*n+1的时间复杂度是O(n2)
- 从分治法的一般设计模式可以看出,用它设计出的程序一般是递归算法(P16)
- 递归与分治算法应满足条件:最优子结构性质与独立子问题性质
- 用回溯法进行状态空间树裁剪分支时一般有两个标准:约束条件和目标函数的界,N皇后问题和0/1背包问题正好是两种不同的类型,其中同时使用约束条件和目标函数的界进行裁剪的是0/1背包问题,只使用约束条件进行裁剪的是N皇后问题
- f(n)=n2+10*n+1000000的时间复杂度是O(n2)
- 算法就是一组有穷的规则,它们规定了解决某一特定类型问题的一系列运算
- f(n)= 6×2n+n2,f(n)的渐进上界是O(2n)
- 以广度优先或以最小耗费方式搜索问题解的算法称为分支限界法(P167)
- 边界条件与递归方程是递归函数的两个要素
- 按照渐近阶从低到高的顺序排列下列表达式:4n^2,logn,3^n, n^(2/3),n!,2^n,结果如下:logn < n^(2/3) < 4n^2 < 2^n < 3^n < n!
- 算法满足的性质:输入、输出、确定性、有限性(P1)
- 算法的复杂性是算法效率的度量,是评价算法优劣的重要依据
- 贪心算法总是做出在当前看来最优的选择。也就是说贪心算法并不从整体最优考虑,它所做出的选择只是在某种意义上的局部最优选择(P95)
- 任何可用计算机求解的问题所需的时间都与其规模有关(P11)
- 分支限界法主要有队列式(FIFO)分支限界法和优先队列式分支限界法(P167)
- 大整数乘积算法是用分治法来设计的
- 衡量一个算法好坏的标准是时间复杂度
- 二分搜索算法是利用分治策略实现的算法(P17)
- 用搜索算法解旅行售货员问题时的解空间树是排列树(P124)
- 0-1背包问题的回溯算法所需的计算时间为O(n2^n)
- 最优子结构性质是贪心算法与动态规划算法的共同点
- 算法中通常以自底向上的方式求解最优解的是动态规划
- 分支限界法解旅行售货员问题时,活结点表的组织形式是优先队列
- 回溯法搜索状态空间树是按照深度优先搜索的顺序
- 将一个难以直接解决的大问题分解成一些规模较小的相同问题,以便各个击破,这属于分治策略的解决方法
- Strassen矩阵乘法是一种利用分治策略实现的算法
- 备忘录方法是动态规划算法的一种变形
- 回溯算法是以深度优先策略进行搜索的(算法)
- 算法分析中,记号O表示渐近上界
二、选择题
- 下列不是动态规划算法基本步骤的是( B)。
A、找出最优解的空间结构 B、构造最优解 C、算出最优解 D、定义最优解
- 背包问题的贪心算法所需的计算时间为( O(nlogn) )。
- 下面哪种函数是回溯法中为避免无效搜索采取的策略( B ) A、递归函数B、剪枝函数 C、随机数函数D、搜索函数
- 以下描述正确的是( B ) A、递归算法只能直接调用自身 B、递归函数是由函数自身给出定义的 C、每个递归函数不一定都要有非递归定义的初始值D、以上都不正确
- 以下描述不正确的是( C) A、组成算法的每条指令是没有歧义的 B、算法中每条指令的执行时间是有限的C、在算法的循环结构中,指令的执行次数可以无限 D、组成算法的每条指令是清晰的
- 二分搜索算法是利用( A)实现的算法。 A、分治策略 B、动态规划法 C、贪心法 D、回溯法
- 下面关于算法的错误说法是(B ) A、算法必须有输出 B、算法必须在计算机上用某种语言实现 C、算法不一定有输入 D、算法必须在有限步执行后能结束
- 0-1背包问题的回溯算法所需的计算时间为( A)
A、O(n2n)B、O(nlogn) C、O(2n) D、O(n)
- 有3个矩阵A维数是{10*100},B维数是{100*5},C维数是{5*50},若按((AB)C)计算,3个矩阵连乘积需要的乘法次数是( A)
A、7500 B、75000 C、750 D、750000
(10 * 5 * 100) = 5000,(10 * 50 * 5) = 2500,5000 + 2500 = 7500
- 用计算机解决问题的步骤一般为:( D )
①编写程序 ②设计算法 ③分析问题 ④调试程序
A.①②③④ B. ③④①② C. ②③①④ D. ③②①④
- 以下哪种算法是以广度优先策略进行搜索的(B )
A、回溯法 B、分支界限法 C、贪心算法 D、随机化算法
- 设序列X={x1,x2,…,xm}和Y={y1,y2,…,yn}的最长公共子序列为Z={z1,z2,…,zk} ,则以下描述不正确的是( D)
A、若xm=yn,则zk=xm=yn,且Zk-1是Xm-1和Yn-1的最长公共子序列
B、若xm≠yn且zk≠xm,则Z是xm-1和Y的最长公共子序列
C、若xm≠yn且zk≠yn,则Z是X和yn-1的最长公共子序列
D、若xm=yn,则zk≠xm≠yn,且Zk-1是Xm-1和Yn-1的最长公共子序列
- 下列算法中通常以深度优先方式系统搜索问题解的是( D )。
A、备忘录法 B、动态规划法 C、贪心法 D、回溯法
- 下列不是动态规划算法基本步骤的是( B )。
A、找出最优解的性质 B、构造最优解
C、算出最优解 D、定义最优解
- Strassen矩阵乘法是利用(A)实现的算法。
A、分治策略 B、动态规划法 C、贪心法 D、回溯法
- 以下对于动态规划描述不正确的是(D )
A、动态规划法与分治法类似,其基本思想也是将待求解问题分解成若干子问题
B、适合于用动态规划求解的问题,经分解得到的子问题往往不是互相独立的
C、具体的动态规划算法多种多样,但是他们具有相同的填表格式
D、动态规划求解问题时和分治法一样,对子问题重复计算多次
动态规划是通过存储子问题的解来避免重复计算,这与分治法不同,分治法中的子问题通常是独立的,因此每个子问题可能会被计算多次。
- 矩阵A是一个p*q矩阵,B是q*r矩阵,则其乘积C=AB是一个(B)矩阵
A、p*q B、p*r C、q*r D、p*q
- 将一个难以直接解决的大问题,分解成一些规模较小的相同问题,以便各个击破。这属于(B )的解决方法。
A、动态规划 B、分治法 C、贪心算法 D、分支界限法
- 动态规划算法适用于解最优化问题,以下哪个不是动态规划法解决问题的步骤(C)
A、找出最优解的性质,并刻画其结构特征
B、递归地定义最优值
C、以自顶向下的方式计算出最优值
D、根据计算最优值时得到的信息,构造最优解
动态规划通常采用自底向上的方式来计算最优值
- 在对问题的解空间树进行搜索的方法中,一个活结点有多次机会成为活结点的是(A )。
A、回溯法 B、分支限界法
C、回溯法和分支限界法 D、回溯法求解子集树问题
- 用计算机解决问题的步骤一般为:( D )
①编写源代码 ②设计算法 ③分析问题 ④调试程序
A.①②③④ B. ③④①② C. ②③①④ D. ③②①④
- 下面关于算法的错误说法是( B )
A、算法必须有输出 B、算法必须在计算机上用某种语言实现
C、算法不一定有输入 D、算法必须在有限步执行后能结束
- 以下对于动态规划描述不正确的是( D)
A、动态规划法与分治法类似,其基本思想也是将待求解问题分解成若干子问题
B、适合于用动态规划求解的问题,经分解得到的子问题往往不是互相独立的
C、具体的动态规划算法多种多样,但是他们具有相同的填表格式
D、动态规划求解问题时和分治法一样,对子问题重复计算多次
- 以下描述正确的是( B )
A、递归算法只能直接调用自身
B、递归函数是由函数自身给出定义的
C、每个递归函数不一定都要有非递归定义的初始值
D、以上都不正确
( 直接或间接地调用自身的算法称为递归算法。
用函数自身给出定义的函数称为递归函数。
递归式的第一式给出了这个函数的初始值,是非递归地定义的。每个递归函数都必须有非递归定义的初始值,否则递归函数无法计算
)
- 衡量一个算法好坏的标准是( C )。
A、运行速度快 B、占用空间少
C、时间复杂度低 D、代码短
- 二分搜索算法是利用( D )实现的算法。
A、动态规划法 B、贪心法 C、回溯法 D、分治策略
- 下列不是动态规划算法基本步骤的是( B )。
A、找出最优解的性质 B、构造最优解 C、算出最优解 D、定义最优解
- 最大效益优先是( A )的一搜索方式。
A、分支界限法 B、动态规划法 C、贪心法 D、回溯法
- Strassen矩阵乘法是利用( A )实现的算法。
A、分治策略 B、动态规划法 C、贪心法 D、回溯法
- 合并排序算法是利用( A )实现的算法。
A、分治策略 B、动态规划法 C、贪心法 D、回溯法
- 背包问题的贪心算法所需的计算时间为( B )。
A、O(n2^n) B、O(nlogn) C、O(2^n) D、O(n)
- 一个问题可用动态规划算法或贪心算法求解的关键特征是问题的(B)。
A、重叠子问题 B、最优子结构性质
C、贪心选择性质 D、定义最优解
- 使用分治法求解不需要满足的条件是( A )。
A 子问题必须是一样的 B 子问题不能够重复
C 子问题的解可以合并 D 原问题和子问题使用相同的方法解
- 下面问题( B )不能使用贪心法解决。
A 单源最短路径问题 B N皇后问题 C 最小花费生成树问题 D 背包问题
- 下列算法中通常以自底向上的方式求解最优解的是( B )。
A、备忘录法 B、动态规划法 C、贪心法 D、回溯法
- 以下不可以使用分治法求解的是(D)。
A 棋盘覆盖问题 B 选择问题
C 归并排序 D 0/1背包问题
- 实现循环赛日程表利用的算法是(A)。
A、分治策略 B、动态规划法 C、贪心法 D、回溯法
- 实现合并排序利用的算法是( A )。
A、分治策略 B、动态规划法 C、贪心法 D、回溯法
- 实现大整数的乘法是利用的算法(C)。
A、贪心法 B、动态规划法 C、分治策略 D、回溯法
- 背包问题的贪心算法所需的计算时间为( B )。
A、O(n2n) B、O(nlogn) C、O(2n) D、O(n)
- 下列哪一种算法是随机化算法( D )
A. 贪心算法 B. 回溯法 C.动态规划算法 D.舍伍德算法
- 下列是动态规划算法基本要素的是( D )。
A、定义最优解 B、构造最优解
C、算出最优解 D、子问题重叠性质
- 二分搜索算法是利用( D )实现的算法。
A、动态规划法 B、贪心法 C、回溯法 D、分治策略
- 有3个矩阵A维数是{10*100},B维数是{100*5},C维数是{5*50},若按((AB)C)计算,3个矩阵连乘积需要的乘法次数是(A )
A、7500 B、75000 C、750 D、750000
- 函数32n+10nlogn的渐进表达式是( C ).
A、2n B、32n C、 nlogn D、10nlogn
- 以下对于动态规划描述不正确的是(D )
A、动态规划法与分治法类似,其基本思想也是将待求解问题分解成若干子问题
B、适合于用动态规划求解的问题,经分解得到的子问题往往不是互相独立的
C、具体的动态规划算法多种多样,但是他们具有相同的填表格式
D、动态规划求解问题时和分治法一样,对子问题重复计算多次
- 哈弗曼编码的贪心算法所需的计算时间为( B )。
A、O(n2n) B、O(nlogn) C、O(2n) D、O(n)
- 以下增长最快的是(D)
A、log2n B、nlog2n C、n2 D、2n
- 以下哪种算法是以深度优先策略进行搜索的( A )
A、回溯法 B、分支界限法 C、贪心算法 D、随机化算法
- 贪心算法不能解决的问题是( C )
A、单源最短路径问题 B、最小花费生成树问题
C、0-1背包问题 D、活动安排问题
- 0-1背包问题的回溯算法所需的计算时间为( A )
A、O(n2n) B、O(nlogn) C、O(2n) D、O(n)
- 在对问题的解空间树进行搜索的方法中,一个活结点有多次机会成为活结点的是(A )。
A、回溯法 B、分支限界法
C、回溯法和分支限界法 D、回溯法求解子集树问题
- 从 分治法 的一般设计模式可以看出,用它设计出的程序一般是递归算法。
- 递归与分治算法应满足条件:最优子结构性质与 独立子问题性质 。
- 回溯法中的解空间树结构通常有两种,分别是_子集树__、__排列树_。
- 分治法的基本思想是首先将待求解问题分解成若干 子问题 。
- 动态规划算法的两个基本要素是___最优子结构____和 ___重叠子问题___ 。
- 动态规划算法的基本思想就将待求问题_分解成若干子问题_、先求解子问题,然后从这些子问题的解得到原问题的解。
- f(n)= 6×2^n+n2,f(n)的渐进性f(n)= O(____2^n______)
- 从分治法的一般设计模式可以看出,用它设计出的程序一般是___递归算法_____ 。
- 动态规划算法的基本思想是首先将待求解问题分解成若干_子问题_______。
- 递归与分治算法应满足条件:最优子结构性质与___独立子问题性质_____。
- 矩阵连乘问题的算法可由 动态规划算法 设计实现。
- 问题的_ 最优子结构 _性质是该问题可用动态规划算法或贪心算法求解的关键特征。
- 若序列X={B,C,A,D,B,C,D},Y={A,C,B,A,B,D,C,D},请给出序列X和Y的一个最长公共子序列_________{BABCD}_________。
- 贪心算法从初始阶段开始,每一个阶段总是作一个使 局部最优 的贪心选择。
- 快速排序算法的性能取决于 划分的对称性 。
- 使用回溯法进行状态空间树裁剪分支时一般有两个标准:约束条件和目标函数的界,N皇后问题和0/1背包问题正好是两种不同的类型,其中同时使用约束条件和目标函数的界进行裁剪的是_____0/1背包______ 问题。
- 二分搜索算法是利用 分治 策略实现的算法。
- 回溯法中的解空间树结构通常有两种,分别是___子集树___、___排列树___。
- 分支限界法主要有____队列___式分支限界法和__优先队列_____式分支限界法。
- 若序列X={A,B,C,A,D,B,C,D},Y={A,A,C,B,A,B,D,C,D},请给出序列X和Y的一个最长公共子序列_____________{ABABCD}________________。
- 贪心算法从初始阶段开始,每一个阶段总是作一个使______局部最优__________ 的贪心选择。
- 使用回溯法进行状态空间树裁剪分支时一般有两个标准:约束条件和目标函数的界,N皇后问题和0/1背包问题正好是两种不同的类型,其中只使用约束条件进行裁剪的是__________N皇后__________问题。
- 备忘录方法是_______动态规划_____算法的变形。
- _贪心选择性质__是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别
- 用计算机解决问题的步骤一般为:(D)
①编写源代码 ②设计算法 ③分析问题 ④调试程序
A.①②③④ B. ③④①② C. ②③①④ D. ③②①④
- 以下描述不正确的是(D)
A、组成算法的每条指令是没有歧义的
B、算法中每条指令的执行时间是有限的
C、组成算法的每条指令是清晰的
D、在算法的循环结构中,指令的执行次数可以无限
- 下面关于算法的错误说法是(B )
A、算法必须有输出 B、算法必须在计算机上用某种语言实现
C、算法不一定有输入 D、算法必须在有限步执行后能结束
- 函数32n+10nlogn的渐进表达式是( C ).
A、2n B、32n C、 nlogn D、10nlogn
- 以下描述正确的是(B )
A、递归算法只能直接调用自身
B、递归函数是由函数自身给出定义的
C、每个递归函数不一定都要有非递归定义的初始值
D、以上都不正确
- 衡量一个算法好坏的标准是( C )。
A、运行速度快 B、占用空间少
C、时间复杂度低 D、代码短
- 贪心算法不能解决的问题是( C )
A、单源最短路径问题 B、背包问题
C、0-1背包问题 D、活动安排问题
- 矩阵连乘问题的算法可由(B)设计实现。
A、分支界限算法 B、动态规划算法
C、贪心算法 D、回溯算法
- 在对问题的解空间树进行搜索的方法中,一个活结点最多有一次机会成为活结点的是( B )。
A、回溯法 B、分支限界法
C、回溯法和分支限界法 D、回溯法求解子集树问题
- 背包问题的贪心算法所需的计算时间为( B )。
A、O(n2n) B、O(nlogn) C、O(2n) D、O(n)
- 二分搜索算法是利用(A)实现的算法。
A.分治策略 B.动态规划法
C.贪心法 D.回溯法
- 下列不是动态规划算法基本步骤的是(B )。
A.找出最优解的性质 B.构造最优解
C.算出最优解 D.定义最优解
- 最大效益优先是(A)的一搜索方式。
A.分支界限法 B.动态规划法
C.贪心法 D.回溯法
- 使用分治法求解不需要满足的条件是(A)。
A. 子问题必须是一样的
B. 子问题不能够重复
C. 子问题的解可以合并
D. 原问题和子问题使用相同的方法解
- 回溯法解旅行售货员问题时的解空间树是( B)。
A.子集树 B.排列树
C.深度优先生成树 D.广度优先生成树
- 下列算法中通常以自底向上的方式求解最优解的是(B )。
A.备忘录法 B.动态规划法
C.贪心法 D.回溯法
- 以下不可以使用分治法求解的是(D)。
A. 棋盘覆盖问题 B.选择问题
C. 归并排序 D. 0/1背包问题
- 实现循环赛日程表利用的算法是(A)。
A.分治策略 B.动态规划法
C.贪心法 D.回溯法
- 实现最大子段和利用的算法是(AB)。
A.分治策略 B.动态规划法
C.贪心法 D.回溯法
- 优先队列式分支限界法选取扩展结点的原则是(C )。
A.先进先出 B.后进先出
C.结点的优先级 D.随机
- 背包问题的贪心算法所需的计算时间为(B )。
A.O(n2n) B.O(nlogn)
C.O(2n) D.O(n)
- 广度优先是( A )的一搜索方式。
A.分支界限法 B.动态规划法
C.贪心法 D.回溯法
- 实现大整数的乘法是利用的算法(C)。
A.贪心法 B.动态规划法
C.分治策略 D.回溯法
- 0-1背包问题的回溯算法所需的计算时间为( A )
A.O(n 2^n) B.O(nlogn)
C.O(2n) D.O(n)
- 回溯法的效率不依赖于下列哪些因素(D )
A.满足显约束的值的个数 B. 计算约束函数的时间
C. 计算限界函数的时间 D. 确定解空间的时间
- 一个问题可用动态规划算法或贪心算法求解的关键特征是问题的(B )。
A.重叠子问题 B.最优子结构性质
C.贪心选择性质 D.定义最优解
- 以深度优先方式系统搜索问题解的算法称为 ( D ) 。
A.分支界限算法 B.概率算法
C.贪心算法 D.回溯算法
- 实现最长公共子序列利用的算法是(B )。
A.分治策略 B.动态规划法
C.贪心法 D.回溯法
三、简答题
1. 阐述回溯算法与分支限界算法的区别和联系,各自强调改善那方面以提高效率,各适合那些问题?
联系:都属于搜索算法,都是在问题的解空间树上搜索问题的解。
区别:
①求解目标:
回溯法的求解目标是找出满足条件的所有解,
分支限界法的求解目标是找出满足条件的一个解或者特定意义下的最优解。
②对解空间树的搜索方式:
回溯法以深度优先的方式搜索解空间树,
分支限界法以广度优先或最小耗费优先的方式搜索解空间树。
适合问题:
回溯算法强调穷举和剪枝来提高效率,适用于求解组合、排列、切割、子集和棋盘等问题;
分支限界算法强调限制搜索范围和优先搜索来提高效率,适用于求解离散值的最优化问题和资源分配问题。
2. 采用动态规划算法必须满足的条件是什么?动态规划算法是通过什么问题的什么特性提高效率的?
- 采用动态规划的算法必须满足的条件是最优子结构性质和子问题重叠性质
- 动态规划算法是通过子问题的重叠特性来提高效率
3. 陈述算法在最坏情况下的时间复杂度和平均时间复杂度;这两种评估算法复杂性的方法各自有什么实际意义?
最坏情况下的时间复杂度是算法在任何输入实例上运行时间的上界,保证了算法的运行时间不会比任何更长
而平均时间复杂度是指所有可能的输入实例均以同等概率出现的情况下,算法的期望运行时间
4. 比较贪心算法与动态规划算法的异同,它们都有那些优势和劣势?
共同点:都需要最优子结构性质,都用来求最优化问题。
不同点:
动态规划:每一步作一个选择,依赖于子问题的解。
贪心方法:每一步作一个选择,不依赖于子问题的解。
动态规划方法的条件:最优子结构性质和重叠子问题性质。
可用贪心方法的条件:最优子结构性质和贪心选择性质。
动态规划:自底向上或自顶向下(备忘录方法)求解;
贪心方法:自顶向下求解。
可用贪心法时,动态规划方法可能不适用;可用动态规划方法时,贪心法可能不适用。
动态规划的优劣
优点
-
-
- 解决所有具有最优子结构的问题。
- 可以在时间复杂度为多项式级别,空间复杂度为常数级别的情况下求解问题。
- 可以考虑状态转移方程中的所有状态,找到最优解。
-
缺点
-
-
- 实现比较困难,需要使用递归和记忆化搜索等技巧。
- 需要很多空间存储中间状态。
- 如果没有最优子结构,导致算法无法求解。
-
2.贪心算法的优劣
优点
-
-
- 实现简单,易于理解。
- 时间复杂度低,适合对实时性要求较高的问题。
- 可以快速求解最优解。
-
缺点
-
-
- 只能求解具有贪心性质的问题。
- 只能得到近似解而非精确的最优解。
- 对于不同的贪心策略,可能会得到不同的解。
-
5. 简述分支限界法和回溯法的异同
相同:都属于搜索算法,都是在问题的解空间树上搜索问题的解。
不同:
①求解目标:
回溯法的求解目标是找出满足条件的所有解,
分支限界法的求解目标是找出满足条件的一个解或者特定意义下的最优解。
②对解空间树的搜索方式:
回溯法以深度优先的方式搜索解空间树,
分支限界法以广度优先或最小耗费优先的方式搜索解空间树。
6. 简述分治法所能解决的问题一般具有的特征。
- 该问题的规模缩小到一定的程度就可以容易地解决
- 该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质
- 利用该问题分解出的子问题的解可以合并为该问题的解
- 该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题
7. 简述分支限界法和回溯法的区别及适用情况。
区别:
①求解目标:
回溯法的求解目标是找出满足条件的所有解,
分支限界法的求解目标是找出满足条件的一个解或者特定意义下的最优解。
②对解空间树的搜索方式:
回溯法以深度优先的方式搜索解空间树,
分支限界法以广度优先或最小耗费优先的方式搜索解空间树。
适用情况:
回溯算法强调穷举和剪枝来提高效率,适用于求解组合、排列、切割、子集和棋盘等问题;
分支限界算法强调限制搜索范围和优先搜索来提高效率,适用于求解离散值的最优化问题和资源分配问题。
8. 简述动态规划与分治法的区别及适用情况。
区别:
-
- 动态规划具有重叠子问题性质,分治法具有子问题独立性质
- 动态规划采用自底向上或自顶向下(备忘录方法)求解的方式解决问题,分治法采用自顶向下的方式解决问题
- 动态规划会存储已解决的子问题的解,分治法不存储中间结果
适用情况
-
- 动态规划法适用于具有最优子结构性质和重叠子问题性质的问题
- 分治法适用于具有最优子结构性质和子问题独立性质的问题
9. 简述利用回溯法解决问题的一般步骤。
- 针对所给问题,定义问题的解空间
- 确定易于搜索的解空间结构
- 以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索
10. 简述设计动态规划算法的4个步骤
- 找出最优解的性质,并且刻画其结构特征
- 递归地定义最优值
- 以自底向上的方式计算最优值
- 根据计算最优值时得到的信息构造最优解
11. 简述分治法的基本思想及步骤。
分治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同递归地解这些子问题,然后将各子问题的解合并得到原问题的解
分治法的步骤
- 分解原问题:将原问题分解为多个子问题
- 解决子问题:递归求解各个子问题
- 合并问题解:将结果合井为原问题解
12. 简述动态规划算法与备忘录法的区别与联系。
备忘录方法是动态规划算法的变形,与动态规划算法一样,备忘录方法用表格保存已解决的子问题答案,在下次需解此问题时,只要简单地查看该子问题的解答,而不必重新计算。备忘录方法与动态规划算法不同的是,备忘录方法的递归方式是自顶向下的,而动态规划算法则是自底向上递归的。因此,备忘录方法的控制结构与直接递归方法的控制结构相同,区别在于备忘录方法为每个解过的子问题建立了备忘录以备需要时查看,避免了相同的子问题的重复求解
13. 简要描述分支限界法的实现过程
- 每个活结点只有一次机会成为扩展结点并一次性产生其所有儿子结点
- 儿子结点导致不可行解或非最优解的儿子结点被舍弃,其余儿子结点被加入活结点表中。如是最小耗费优先,活结点表需要重新排序
- 此后,从活结点表中取下一结点成为当前扩展结点,并重复上述结点扩展过程。这个过程一直持续到所需的解或活结点表为空时为止
14. 简述分治法的基本思想及步骤。
治法的基本思想是将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同递归地解这些子问题,然后将各子问题的解合并得到原问题的解
分治法的步骤
- 分解原问题:将原问题分解为多个子问题
- 解决子问题:递归求解各个子问题
- 合并问题解:将结果合井为原问题解
15. 简述动态规划法的基本思想及步骤。
动态规划法的基本思想是将待求解问题分解成若干子问题,先求解子问题,再结合这些子问题的解得到原问题的解
动态规划的步骤:
- 找出最优解的性质,并且刻画其结构特征
- 递归地定义最优值
- 以自底向上的方式计算最优值
- 根据计算最优值时得到的信息构造最优解
16. 简述回溯法的算法思想。
- 在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树
- 算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解
- 如果不包含,则跳过对该结点为根的子树的搜索,继续该结点兄弟结点的搜索
- 否则,进入该子树,继续按深度优先策略搜索
四、算法应用题
1. 使用回溯法解0/1背包问题:n=3,C=50,V={60,100,120},W={10,20,30},要求用一棵完全二叉树表示其解空间。画出其解空间树,计算其最优值,并构造最优解
n应该是指物品数量,c应该是指背包容量,V应该是指价值,W应该是指物品重量
最优解是选择物品2和3,最优值为220
2. 使用分支限界解0/1背包问题:n=3,C=50,V={60,100,120},W={10,20,30},要求用一棵完全二叉树表示其解空间。画出其解空间树,计算其最优值,并构造最优解。
最优解是选择物品2和3,最优值为220
3. 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。现输入导弹依次飞来的高度,计算这套系统最多能拦截多少导弹及拦截的各导弹高度是多少,并写出推导过程。输入:389 154 155 302 299 170 158 65 320 296 111 222 555 68 189
导弹高度 | 389 | 154 | 155 | 302 | 299 | 170 | 158 | 65 | 320 | 296 | 111 | 222 | 555 | 68 | 189 |
拦截个数 | 1 | 2 | 2 | 2 | 3 | 4 | 5 | 6 | 2 | 4 | 6 | 5 | 1 | 7 | 6 |
最多拦截个数为7个,拦截的导弹各高度为389,302,299,170,158,111,68
五、算法实现题
1. 把一个字符串(数组)进行逆序操作,如“abc"逆序为“cba” ,要求空间复杂度为O(1)
#include<bits/stdc++.h>
using namespace std;
int main(){
char str[10];
cin>>str;
int l=0,r=strlen(str)-1;
while(l<r){
char c=str[l];
str[l]=str[r];
str[r]=c;
l++;
r--;
}
cout<<str;
return 0;
}
2. 请用递归算法实现判断一个数组是否是从小到大排序,要求递归函数返回bool值. 比如数组1,2,3,4,5,6是从小到大排序,递归函数返回true
#include<bits/stdc++.h>
using namespace std;
int a[10];
int n;
bool dg(int step){
if(step==n){
return true;
}
if(a[step]>=a[step-1]){
return dg(step+1);
}
return false;
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
bool ans=dg(1);
if(ans){
cout<<"数组满足从小到大排序";
}
else{
cout<<"数组不满足从小到大排序";
}
return 0;
}
3. 五对括号可以有多少种匹配排列方式?
#include<bits/stdc++.h>
using namespace std;
int ans;
void dg(int l,int r){
//如果括号匹配
if(l==r&&l==5){
ans++;
return;
}
//左括号没有五个
if(l<5)dg(l+1,r);
//右括号出现次数比左括号少
if(r<l)dg(l,r+1);
}
int main(){
dg(0,0);
cout<<ans;
return 0;
}
4. 求一个数组的最长递减(上升)子序列比如{9,4,3,2,5,4,3,2}的最长递减子序列为 {9,5,4,3,2}
#include<bits/stdc++.h>
using namespace std;
int n;
int a[10];
int dp[10];
int ans;
vector<int>v;
int main() {
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
dp[i]=1;
}
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(a[i]<a[j]){
dp[i]=max(dp[i],dp[j]+1);
}
}
ans=max(ans,dp[i]);
}
int temp=ans;
while(temp>0){
n--;
if(dp[n]==temp){
v.push_back(a[n]);
temp--;
}
}
reverse(v.begin(),v.end());
cout<<ans<<endl;
for(auto it:v){
cout<<it<<' ';
}
return 0;
}
5. 请用递归算法实现判断一个字符串是否是对称字符串,要求递归函数返回bool值. 比如“abcdcba”是对称字符串,递归函数返回true
#include<bits/stdc++.h>
using namespace std;
string s;
bool dg(int l,int r){
if(l>=r){
return true;
}
if(s[l]==s[r]){
return dg(l+1,r-1);
}
return false;
}
int main() {
cin>>s;
bool ans=dg(0,s.size()-1);
if(ans){
cout<<"字符串是对称的";
}
else{
cout<<"字符串不是对称的";
}
return 0;
}
6. 请用递归算法求和,公式为:f(n)=2+4+6+.....+(2*n),n为正整数,f(n)不会超出整数范围。要求递归函数返回int类型
#include<bits/stdc++.h>
using namespace std;
int n;
int dg(int step){
if(step==2*n){
return 2*n;
}
return step+dg(step+2);
}
int main() {
cin>>n;
int ans=dg(2);
cout<<ans;
return 0;
}
7. 已知某数列符合规则:f(n)=f(n-1)+f(n-2)+f(n-3),且n为自然数,f(1)=1,f(2)=1,f(3)=1,那么请求第n个数是多少。要求时间复杂度为O(n),空间复杂度为O(1)
#include<bits/stdc++.h>
using namespace std;
int n;
int ans=1;
int a=1,b=1,c=1;
int main(){
cin>>n;
for(int i=4;i<=n;i++){
ans=a+b+c;
a=b;
b=c;
c=ans;
}
cout<<ans;
return 0;
}
8. 最大子段和问题:给出一个序列,其子段为该序列的一个连续的区间。例如:(1 -1 2 2 3 -3 4 -4) ,(2 2 3 -3 4)为他的一个子段。给出一个序列,求出数字求和最大的一个子段。例如上面的序列, (2 2 3 -3 4)就是一个最大的子段,数字的总和为8
#include<bits/stdc++.h>
using namespace std;
int n;
int a[15];
int b[15];
int main() {
cin>>n;
int left=-1,right;//记录最大字段序列边界
for(int i=0;i<n;i++){
cin>>a[i];
b[i]=b[i-1]+a[i];//前缀和
}
int l=0,ans=-1e9;
for(int i=0;i<n;i++){
if(b[i]-l>ans){//是否更新最大值和右边界
ans=b[i]-l;
right=i;
}
if(b[i]<=l){//是否更新最小值和左边界
l=b[i];
left=i;
}
}
cout<<"最大子段和的值为"<<ans<<endl;
cout<<"最大字段和的序列为";
for(int i=left+1;i<=right;i++){//输出序列
cout<<a[i]<<' ';
}
return 0;
}
9. 键盘输入n个正整数(互不相等),找出其中和等于m的所有组合。
【输入输出样例】输入:5(m的值) 1 2 3 4 5(n个正整数)
【输出】:1 4
2 3
5
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[15];
vector<int>v;
void dg(int sum,int current){
if(sum==m){
for(auto it:v){
cout<<it<<' ';
}
cout<<endl;
return;
}
for(int i=current+1;i<n;i++){
if(sum+a[i]<=m){
v.push_back(a[i]);
dg(sum+a[i],i);
v.pop_back();
}
else{
return;
}
}
}
int main() {
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
dg(0,-1);
return 0;
}
10. 设计递归算法求解如下多项式:
x=1,n=1 f=5/6
x=1,n=2 f=5/6+1/120=101/120
x=1,n=3 f=101*6*7/(120*6*7)+1/5040=4243/5040
#include<bits/stdc++.h>
using namespace std;
int n,x;
int jiecheng(int x){
if(x==1)return 1;
return x*jiecheng(x-1);
}
double dg(int x,int current){
if(current==1){
return x;
}
int fuhao;
if((current-1)/2%2==0)fuhao=1;
else fuhao=-1;
double temp=fuhao*pow(x,current)/jiecheng(current);
// cout<<fuhao*pow(x,current)<<' '<<current<<' '<<jiecheng(current)<<' '<<temp<<endl;
return temp+dg(x,current-2);
}
int main() {
cout<<"请输入n和x"<<endl;
cin>>n>>x;
cout<<dg(x,2*n+1);
return 0;
}
11. 编写函数double getRestul(int n),它的功能是:根据以下公式计算结果S
#include<bits/stdc++.h>
using namespace std;
int n;
double dg(int current){
if(current==1){
return 1;
}
int fuhao;
if((current+1)/2%2==1)fuhao=1;
else fuhao=-1;
double temp=fuhao*1.0/current;
// cout<<fuhao<<' '<<current<<' '<<temp<<endl;
return temp+dg(current-2);
}
int main() {
cin>>n;
cout<<dg(2*n-1);
return 0;
}
12. 有一头母牛,它每年年初生一头小母牛。每头小母牛从第四个年头开始,每年年初也生一头小母牛。请编程实现在第n年的时候,共有多少头母牛
#include<bits/stdc++.h>
using namespace std;
int n;
int dg(int x){
if(x<=4)return x;
return dg(x-1)+dg(x-3);
}
int main() {
cin>>n;
cout<<dg(n);
return 0;
}
13. 给定n个正整数wi和一个正整数m,在这n个正整数中找出一个子集,使得子集中的正整数之和等于m
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[15];
vector<int>v;
bool result=false;
void dg(int sum,int current){
if(sum==m){
result=true;
for(auto it:v){
cout<<it<<' ';
}
return;
}
if(result==true)return;
for(int i=current+1;i<n;i++){
if(sum+a[i]<=m){
v.push_back(a[i]);
dg(sum+a[i],i);
v.pop_back();
}
else{
return;
}
}
}
int main() {
cin>>n>>m;
for(int i=0;i<n;i++){
cin>>a[i];
}
sort(a,a+n);
dg(0,-1);
if(!result){
cout<<"No solution!"<<endl;
}
return 0;
}
14. 编写函数double getRestul(int n),它的功能是:根据以下公式计算结果S
#include<bits/stdc++.h>
using namespace std;
int n;
double dg(int current){
if(current==1){
return 0.5;
}
int fuhao;
if(current%2==1)fuhao=1;
else fuhao=-1;
double temp=fuhao*1.0/(2*current);
// cout<<fuhao<<' '<<2*current<<' '<<temp<<endl;
return temp+dg(current-1);
}
int main() {
cin>>n;
cout<<dg(n);
return 0;
}
15. 求最长下降序列问题。问题描述:某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统。但是这种导弹拦截系统有一个缺陷:虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。现输入导弹依次飞来的高度,计算这套系统最多能拦截多少导弹。输入:389 207 155 300 299 170 158 65 输出:6
#include<bits/stdc++.h>
using namespace std;
int n;
int a[15];
int dp[15];
int ans;
int main() {
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
dp[i]=1;
}
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(a[i]<=a[j]){
dp[i]=max(dp[i],dp[j]+1);
}
}
ans=max(ans,dp[i]);
}
cout<<ans;
return 0;
}
16. 一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法,并输出每种跳法具体怎么跳
#include<bits/stdc++.h>
using namespace std;
int n;
vector<int>temp;
map<int,vector<int>>mp;
int ans;
void dg(int step){
if(step>n)return;
if(step==n){
mp[ans]=temp;
ans++;
return;
}
temp.push_back(1);
dg(step+1);
temp.pop_back();
temp.push_back(2);
dg(step+2);
temp.pop_back();
}
int main() {
cin>>n;
dg(0);
cout<<"一共有"<<ans<<"解法"<<endl;
cout<<"具体解法如下:"<<endl;
for(int i=0;i<ans;i++){
for(auto it:mp[i]){
cout<<it<<' ';
}
cout<<endl;
}
return 0;
}
17. 某公司拟将5百万元,向A、B、C三个项目追加投资,三个项目可以有不同的投资额度,相应的效益值如表所示,问如何分配资金,才使总效益值最大?下表是追加投资到各项目的额度收益表。
0 | 1 | 2 | 3 | 4 | 5 | |
A | 47 | 51 | 59 | 71 | 76 | 86 |
B | 49 | 52 | 61 | 71 | 78 | 88 |
C | 46 | 70 | 76 | 88 | 88 | 98 |
//不知道是不是这么算的
#include<bits/stdc++.h>
using namespace std;
int ans;
int dp[6][6][6];
int a[6]={47,51,59,71,76,86};
int b[6]={49,52,61,71,78,88};
int c[6]={46,70,76,88,88,98};
int main() {
for(int i=0;i<6;i++){
for(int j=0;j<=5-i;j++){
int temp=a[i]+b[j]+c[5-i-j];
ans=max(ans,temp);
// cout<<i<<' '<<j<<' '<<5-i-j<<' '<<temp<<endl;
}
}
cout<<ans;
return 0;
}
18. 有m件物品,它们的重量分别是W1,W2,…,Wm,它们的价值分别是V1,V2,…,Vm,现在给你个承重为n的背包,如何让背包里装入的物品具有最大的价值总和。要求用分支限界法进行算法设计及实现,并且需要有合适的剪枝函数(可行性约束、限界函数)
#include<bits/stdc++.h>
using namespace std;
int ans;
int w[10005];
int v[10005];
int n, m;
map<int, int>mp;
void bfs() {
queue<pair<int, int>>q;
q.push({0, 0});
int temp = 0;
int cnt = 1;
while (q.size()) {
int ls = cnt;
cnt = 0;
while (ls--) {
int top = q.front().first;
int jiazhi = q.front().second;
// cout<<top<<' '<<jiazhi<<endl;
q.pop();
if (temp < n) {
if (top + w[temp] <= m) {
q.push({top + w[temp], jiazhi + v[temp]});
ans = max(ans, jiazhi + v[temp]);
cnt++;
}
q.push({top, jiazhi});
cnt++;
ans = max(ans, jiazhi);
}
}
temp++;
}
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
cin >> w[i] >> v[i];
}
bfs();
cout << ans;
return 0;
}
19. 有m件物品,它们的重量分别是W1,W2,…,Wm,它们的价值分别是V1,V2,…,Vm,现在给你个承重为n的背包,如何让背包里装入的物品具有最大的价值总和。要求用回溯法进行算法设计及实现,并且需要有合适的剪枝函数(可行性约束、限界函数)
#include<bits/stdc++.h>
using namespace std;
int ans;
int w[10005];
int v[10005];
int n, m;
map<int, int>mp;
void dfs(int top, int jiazhi, int step) {
if (step == n) {
ans = max(ans, jiazhi);
return;
}
if (top + w[step] <= m) {
dfs(top + w[step], jiazhi + v[step], step + 1);
}
dfs(top, jiazhi, step + 1);
}
int main() {
cin >> n >> m;
for (int i = 0; i < n; i++) {
cin >> w[i] >> v[i];
}
dfs(0, 0, 0);
cout << ans;
return 0;
}
20. 使用递归与分治算法实现:输入一个自然数,若为偶数,则把它除以2,若为奇数,则把它乘以3加1。经过如此有限次运算后,总可以得到自然数值1。求1000以内经过运算次数最多而得到1的数。如输入自然数为22 ,运算结果序列为:22 11 34 17 52 26 13 40 20 10 5 16 8 4 1,则运算次数为15 ,再如输入自然数为9 ,运算结果为:9 28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1,则运算次数为19
#include<bits/stdc++.h>
using namespace std;
int ans;
int cnt;
int zrs;
void dg(int n){
if(n==1)return;
ans++;
if(n%2==0)dg(n/2);
else dg(3*n+1);
}
int main() {
for(int i=1;i<=1000;i++){
dg(i);
if(ans>cnt){
cnt=ans;
zrs=i;
}
ans=0;
}
cout<<zrs<<' '<<cnt;
return 0;
}
21. 高矮不同的12个人,排成两排,每排必须是从矮到高排列,而且第二排比对应的第一排的人高,问排列方式有多少种?
#include<bits/stdc++.h>
using namespace std;
int n=12;
int a[15];
int b[3][7];
int f[15];
int ans;
void dg(int step){
if(step==12){
ans++;
return;
}
int x=step/6+1;
int y=step%6+1;
for(int i=0;i<12;i++){
if(!f[a[i]]&&a[i]>b[x-1][y]&&a[i]>b[x][y-1]){
b[x][y]=a[i];
f[a[i]]++;
dg(step+1);
f[a[i]]--;
}
}
}
int main() {
for(int i=0;i<12;i++){
a[i]=i+1;
}
dg(0);
cout<<ans;
return 0;
}
#include<bits/stdc++.h>
using namespace std;
int h(int n){
if(n<2)return 1;
int res=0;
for(int i=0;i<n;i++)res+=h(i)*h(n-i-1);
return res;
}
int main(){
cout<<h(6);
return 0;
}
22. 某公司购买长钢条,将其切为短钢条出售,假设切割没有成本,公司希望知道最佳的切割方案!假设我们知道一段长度为i的钢条的价格为pi(i = 1,2,3...),钢条长度均为整数单位,下面给出一个价格表:
长度i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
价格p[i] | 1 | 5 | 8 | 9 | 10 | 17 | 17 | 20 | 24 | 30 |
给定一长度为n的钢条和一张价格表(i =1, 2,3...n),求切割钢条的具体方案,使得利润最大,可以不进行切割
#include<bits/stdc++.h>
using namespace std;
int n;
int p[20]={0,1,5,8,9,10,17,17,20,24,30};
int dp[100005];
int main() {
cin>>n;
for(int i=0;i<=20;i++)dp[i]=p[i];
for(int i=1;i<=n;i++){
for(int j=0;j<=i-j;j++){
dp[i]=max(dp[i],dp[j]+dp[i-j]);
}
}
cout<<dp[n];
return 0;
}
23. 使用递归与分治算法实现:输入一个自然数,若为偶数,则把它除以2,若为奇数,则把它乘以3加1。经过如此有限次运算后,总可以得到自然数值1。求经过多少次可得到自然数1。如输入自然数为22 ,运算结果序列为:22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1,则运算次数为15 ,再如输入自然数为9 ,运算结果为:9 28 14 7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1,则运算次数为19
#include<bits/stdc++.h>
using namespace std;
vector<int>temp;
map<int,vector<int>>mp;
int ans;
void dg(int n){
if(n==1)return;
if(n%2==0)n/=2;
else n=3*n+1;
ans++;
dg(n);
}
int main() {
int n;
cin>>n;
dg(n);
cout<<ans;
return 0;
}
更好的阅读体验:
那个由于没有会员,所以有效期只有半年,如有后来者需要更好的阅读体验的话后台或评论区踢一下~