📖 习题集
📃 选择题
可以在选择题巩固基础概念
- 二分搜索算法是利用( A )实现的算法。
A. 分治策略
B. 动态规划法
C. 贪心法
D. 回溯法 - 最大效益优先是( A )的一搜索方式。
A. 分支界限法
B. 动态规划法
C. 贪心法
D. 回溯法 - 最长公共子序列算法利用的算法是( B )。
A. 分支界限法
B. 动态规划法
C. 贪心法
D. 回溯法 - 下列算法中通常以自底向上的方式求解最优解的是( B )。
A. 备忘录法
B. 动态规划法
C. 贪心法
D. 回溯法 - 衡量一个算法好坏的标准是(C )。
A 运行速度快
B 占用空间少
C 时间复杂度低
D 代码短 - 以下不可以使用分治法求解的是(D )。
A 棋盘覆盖问题
B 选择问题
C 归并排序
D 0/1背包问题(回溯. 分支限界. 动态规划) - 实现循环赛日程表利用的算法是( A )。
A. 分治策略
B. 动态规划法
C. 贪心法
D. 回溯法 - 实现最长公共子序列利用的算法是( B )。
A. 分治策略
B. 动态规划法
C. 贪心法
D. 回溯法 - 下面不是分支界限法搜索方式的是( D )。
A. 广度优先
B. 最小耗费优先
C. 最大效益优先
D. 深度优先 - 下列算法中通常以深度优先方式系统搜索问题解的是( D )。
A. 备忘录法
B. 动态规划法
C. 贪心法
D. 回溯法 - 一个问题可用动态规划算法或贪心算法求解的关键特征是问题的( B )。
A. 重叠子问题
B. 最优子结构性质
C. 贪心选择性质
D. 定义最优解 - 广度优先是( A )的一搜索方式。
A. 分支界限法
B. 动态规划法
C. 贪心法
D. 回溯法(深度优先) - 背包问题的贪心算法所需的计算时间为( B )。
A. O(n2n)
B. O(nlogn)
C. O(2n)
D. O(n) - 实现最大子段和利用的算法是( B )。
A. 分治策略
B. 动态规划法
C. 贪心法
D. 回溯法 - 实现棋盘覆盖算法利用的算法是( A )。
A. 分治法
B. 动态规划法
C. 贪心法
D. 回溯法 - 下面是贪心算法的基本要素的是( C )。
A. 重叠子问题
B. 构造最优解
C. 贪心选择性质
D. 定义最优解 - 回溯法的效率不依赖于下列哪些因素( D )
A.满足显约束的值的个数
B. 计算约束函数的时间
C. 计算限界函数的时间
D. 确定解空间的时间 - 下面哪种函数是回溯法中为避免无效搜索采取的策略( B )
A.递归函数
B.剪枝函数
C. 随机数函数
D.搜索函数 - 以深度优先方式系统搜索问题解的算法称为 ( D ) 。
A. 分支界限算法
B. 概率算法
C. 贪心算法
D. 回溯算法 - 贪心算法与动态规划算法的主要区别是( B )。(cd为动态规划的基本步骤)
A. 最优子结构
B. 贪心选择性质
C. 构造最优解
D. 定义最优解 - 采用最大效益优先搜索方式的算法是( A )。
A. 分支界限法
B. 动态规划法
C. 贪心法
D. 回溯法 - ( D )是贪心算法与动态规划算法的共同点。
A. 重叠子问题
B. 构造最优解
C. 贪心选择性质
D. 最优子结构性质 - 矩阵连乘问题的算法可由( B)设计实现。
A. 分支界限算法
B. 动态规划算法
C. 贪心算法
D. 回溯算法 - 0-1背包问题的回溯算法所需的计算时间为( A )
A. O( n 2 n^2 n2)
B. O(nlogn)
C. O(2n)
D. O(n) - 背包问题的贪心算法所需的计算时间为( B )
A. O(n2n)
B. O(nlogn)
C. O(2n)
D. O(n) - 使用分治法求解不需要满足的条件是(A )。
A 子问题必须是一样的
B 子问题不能够重复
C 子问题的解可以合并
D 原问题和子问题使用相同的方法解 - 下面问题(B )不能使用贪心法解决。
A 单源最短路径问题
B N皇后问题
C 最小花费生成树问题
D 背包问题 - 下列算法中不能解决0/1背包问题的是(A )
A 贪心法
B 动态规划
C 回溯法
D 分支限界法 - 回溯法搜索状态空间树是按照(C )的顺序。
A 中序遍历
B 广度优先遍历
C 深度优先遍历
D 层次优先遍历 - 采用广度优先策略搜索的算法是( A )。
A. 分支界限法
B. 动态规划法
C. 贪心法
D. 回溯法 - 实现合并排序利用的算法是( A )。
A. 分治策略
B. 动态规划法
C. 贪心法
D. 回溯法 - 下列是动态规划算法基本要素的是( D )。
A. 定义最优解
B. 构造最优解
C. 算出最优解(基本步骤)
D. 子问题重叠性质
📃 填空题
- 算法的复杂性有 时间复杂性 和 空间复杂性 之分。
- 程序是 算法 用某种程序设计语言的具体实现。
- 算法的“确定性”指的是组成算法的每条 指令 是清晰的,无歧义的。
- 矩阵连乘问题的算法可由 动态规划 设计实现。
- 算法是指解决问题的 一种方法 或 一个过程 。
- 快速排序算法的性能取决于 划分的对称性 。
- 从分治法的一般设计模式可以看出,用它设计出的程序一般是 递归算法 。
- 问题的 最优子结构性质 是该问题可用动态规划算法或贪心算法求解的关键特征。
- 以深度优先方式系统搜索问题解的算法称为 回溯法 。
- 任何可用计算机求解的问题所需的时间都与其 规模 有关。
- 计算一个算法时间复杂度通常可以计算 循环次数,基本操作的频率 或 计算步。
- 回溯法搜索解空间树时,常用的两种剪枝函数为 约束函数 和 限界函数。
- 解决0/1背包问题可以使用 动态规划、回溯法 和 分支限界法,其中不需要排序的是 动态规划 ,需要排序的是 回溯法 ,分支限界法 。
- 使用回溯法进行状态空间树裁剪分支时一般有两个标准:约束条件 和 目标函数的界,N皇后问题和0/1背包问题正好是两种不同的类型,其中同时使用约束条件和目标函数的界进行裁剪的是 0/1背包问题 ,只使用约束条件进行裁剪的是 N皇后问题 。
- 回溯法是一种既带有 系统性 又带有 跳跃性 的搜索算法。
- 动态规划算法的两个基本要素是. 最优子结构性质 和 重叠子问题 性质。
- 贪心算法的基本要素是 贪心选择性 和 最优子结构 性质 。
- 动态规划算法的基本思想是将待求解问题分解成若干 子问题 ,先求解 子问题 ,然后从这些 子问题 的解得到原问题的解。
- 算法是由若干条指令组成的有穷序列,且要满足 输入、输出 、确定性 和 有限性 四条性质。
- 快速排序算法是基于 分治策略 的一种排序算法。
- 以广度优先或以最小耗费方式搜索问题解的算法称为 分支限界法 。
📚不进🧠
一、基础入门
📙 时间复杂度
✨ 排序的时间复杂度
🌰 时间复杂度按阶排序
📙 算法伪码
📙 函数的渐近界
✨ 渐近上界大O
✨ 渐近下界 Ω
✨ 渐近精确界 θ
✨ 小 o 符号
✨ 小 ω 符号
📙 主定理解递归方程
📕 汉诺塔问题
二、分治策略
📕 芯片测试
✨ 蛮力算法
✨ 分治算法
📕 选第二大
✨ 锦标赛算法
总的时间复杂度:
n
+
⌈
l
o
g
n
⌉
−
1
n + \lceil log n \rceil -1
n+⌈logn⌉−1
三、动态规划
📕 一般背包问题
标记函数用于追踪解
📕 01 背包问题
📕 最长公共子序列
✨ 动态规划 DP
✨ 蛮力解法
📕 矩阵连乘问题
✨ 动态规划算法
✨ 蛮力算法
四、贪心
📙 数学归纳法
✨ 基础知识
✨ 算法正确性归纳证明
✨ 小结
📕 最优装载问题
📕 最小延迟调度问题
五、回溯
📕 图的着色
时间复杂度:O(
n
m
n
nm^n
nmn)
代码实现
👨🏫 图的着色(回溯法)
#include<iostream>
using namespace std;
int c[100][100]; //邻接矩阵
int color[100]; //记录每个顶点的颜色
int count,m,n; //count记录方案数 n个顶点 m种颜色
int Check(int k) //检查第i个顶点的颜色是否满足条件
{
for(int i=1;i<=k;i++)
{
if(c[k][i]==1&&color[i]==color[k]) //k与i之间相连并且i顶点的颜色与k顶点的颜色相同
return 0;
}
return 1;
}
void GraphColor(int step)
{
if(step==n+1) //表示前面所有的顶点颜色都已经填完
{
for(int i=1;i<=n;i++)
printf("%d ",color[i]);
count++;
printf("\n");
return ;
}
else
{
for(int i=1;i<=m;i++)
{
color[step]=i; //首先将这个顶点颜色换为i
if(Check(step)==1) //检查是否符合条件
{
GraphColor(step+1); //符合条件则走下一步
}
color[step]=0; //回溯 置为0
}
}
}
int main(void)
{
int a,b;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
cin>>c[i][j];
}
GraphColor(1);
printf("%d",count);
return 0;
}
📖 学习通
📓 课后作业
第一章 作业 1
📕 求时间复杂度
📕 求各种渐近界
第一章 作业 2
📕 递归树分析复杂度
📕 主定理分析复杂度
📕 迭代法分析复杂度
📕 函数的阶
第二章 作业 1
📕 汉诺塔
📕 找不合格砝码(求递推方程)
📕 比较算法时间复杂度
第二章 作业 2
📕 插入排序
📙 分治法的设计思想和三个阶段
参考答案
将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。
分治法将一个难以直接解决的大问题划分成一些规模较小的子问题,分别求解各个子问题,再合并子问题的解得到原问题的解。一般来说,分治法的求解过程由以下三个阶段组成:
(1)划分:把规模为 n 的原问题划分为 k 个(通常 k = 2)规模较小的子问题。
(2)求解子问题:分别求解各个子问题。
(3)合并:把各个子问题的解合并起来。
第三章 作业 1
📕 二分
📙 动态规划的设计要素
📙 动态规划和分治的对比
第三章 作业 2
📕 硬币买单(完全背包)
参考答案
📕 货币找零问题(01 背包)
第四章 作业 1
📕 顾客最少等待
参考答案
第四章 作业 2
📕 野外考察队
参考答案
第五章 作业 1
📕 求不等式所有解
以下仅供参考
public class Main {
static int cnt, N = 10;
static boolean[][][] st = new boolean[N][N][N];
public static void main(String[] args) {
// dfs 递归搜一下
// 3 * a + 4 * b + 2 * c <= 10 ,求 a b c 的所有解
dfs(0, 0, 0);
}
private static void dfs(int a, int b, int c) {
int x = 3 * a + 4 * b + 2 * c;
if (x > 10)
return;
if (x <= 10 && !st[a][b][c]) {
st[a][b][c] = true;
System.out.println(++cnt + ": x1 =" + a + ",x2=" + b + ",x3=" + c + ",和: " + x);
}
dfs(a + 1, b, c);
dfs(a, b + 1, c);
dfs(a, b, c + 1);
}
}
第五章 作业 2
📕 分支界限巴拉巴拉
第五章 作业 3
TODO
📔 随堂小测