【算法设计与分析】期末复习

news2024/11/15 19:38:29

文章目录

  • 复习大纲
    • 第一章算法概述
      • 1.1算法与程序
      • 1.2 算法复杂性分析
    • 第二章递归与分治策略
      • 分治法的基本思想
      • 递归与分治的关系:
      • 用分治法解决的问题的几个特征:
      • 例题:
    • 第三章动态规划
      • 动态规划的基本思想:
      • 分治与动态规划算法的异同:
      • 理解动态规划算法的基本要素:
      • 动态规划算法求解问题的步骤:
      • 例题:
    • 第四章贪心算法
      • 理解贪心算法的基本要素:
      • 贪心算法与动态规划算法的异同点:
      • 0-1背包问题能不能用贪心算法求解?为什么?
      • 例题:
    • 第五章回溯法
      • 回溯法的基本思想:
      • 回溯法解题步骤
      • 用回溯法解题的特征:
      • 回溯法的算法框架:
      • 影响回溯法的效率因素:
      • 例题(看PPT):
    • 第六章分支限界法
      • 分支限界法的基本思想:
      • 分支限界法与回溯法的异同:
      • 分支限界法的实现方式:
      • 例题:
  • 复习题库
    • 选择题
    • 填空题
    • 算法填空
    • 简答题
      • 1.分治法的基本思想:
      • 2.设计动态规划算法的主要步骤为:
      • 3. 分治法与动态规划法异同
      • 4. 分支限界法与回溯法异同
      • 5.贪心算法与动态规划算法的主要区别
      • 6. 分治法所能解决的问题一般具有的几个特征是:
      • 7. 用分支限界法设计算法的步骤是:
      • 8. 常见的两种分支限界法的算法框架
      • 9. 回溯法中常见的两类典型的解空间树:
      • 10. 分支限界法的搜索策略是:
      • 11、回溯法的基本思想
    • 算法设计题

复习大纲

第一章算法概述

1.1算法与程序

算法:是解决问题的一种方法或一个过程,是由若干条指令组成的有穷序列。
算法性质
1.输入:有零个或多个
2.输出:至少一个
3.确定性:组成算法的每条指令清晰无歧义
4.有限性:算法中每条指令的执行次数和执行时间是有限的
5.算法与程序的区别:程序是算法用某种程序设计语言的具体实现,可以不满足有限性。

1.2 算法复杂性分析

1.算法的复杂性分时间复杂性空间复杂性
2.三种情况下的时间复杂性,可操作性最好最有实际价值的是最坏情况下的时间复杂性
3.算法复杂性的渐进分析:O,o,Ω,ω,Θ

第二章递归与分治策略

分治法的基本思想

将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。递归地解这些子问题,然后将各子问题的解合并得到原问题的解。

递归与分治的关系:

由分治法产生的子问题往往是原问题的较小模式,反复应用分治法,可以使子问题与原问题类型一致且规模不断缩小,最终使子问题缩小到很容易求解,因此用递归求解

用分治法解决的问题的几个特征:

•问题的规模缩小到一定的程度可以容易地解决
•问题可以分解为若干个规模较小的相同问题
•利用原问题分解出的子问题的解可以合并为原问题的解
•问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。如果子问题不是相互独立的,可以用动态规划法

例题:

深刻理解算法的设计并能够进行时间复杂度分析
排列问题(包括有重复元素的情况),二分搜索,大整数乘法和矩阵乘法的分治思想,合并排序,快速排序,棋盘覆盖的思想。

第三章动态规划

动态规划的基本思想:

将待求解问题分解成若干个子问题,如果各个子问题不是独立的,不同的子问题的个数只是多项式量级,为避免大量的重复计算,用一个表记录所有已解决的子问题的答案,而在需要的时候再找出已求得的答案。

分治与动态规划算法的异同:

分治法与动态规划法的相同点是:将待求解的问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
两者的不同点是:适合于用动态规划法求解的问题,经分解得到的子问题往往不是互相独立的。而用分治法求解的问题,经分解得到的子问题往往是互相独立的。

理解动态规划算法的基本要素:

  • 最优子结构性质:问题的最优解包含了其子问题的最优解。
  • 重叠子问题性质:有些子问题被反复计算多次。

动态规划算法求解问题的步骤:

  • 找出最优解的性质,并刻画其结构特征
  • 递归地定义最优值
  • 自底向上的方式计算出最优值
  • 构造最优解

例题:

深刻理解矩阵连乘问题、最长公共子序列问题最大子段和问题0-1背包问题的动态规划算法,并进行时间复杂度和空间复杂度分析。

第四章贪心算法

理解贪心算法的基本要素:

  • 贪心选择性质:所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。
  • 最优子结构性质。

贪心算法与动态规划算法的异同点:

(1)共同点:都需要最优子结构性质,都用来求最优化问题。
(2)不同点:
动态规划:每一步作一个选择—依赖于子问题的解
贪心方法:每一步作一个选择—不依赖于子问题的解
动态规划方法的条件:子问题的重叠性质。
可用贪心方法的条件:最优子结构性质;贪心选择性质。
动态规划:自底向上或自顶向下(备忘录方法)求解;
贪心方法:自顶向下求解。

0-1背包问题能不能用贪心算法求解?为什么?

对于部分背包问题,依照贪心选择策略,可以得到最优解。而0-1背包问题,贪心选择之所以不能得到最优解,是因为在这种情况下,它无法保证最终能将背包装满,部分闲置的背包空间使每公斤背包空间的价值降低了。因而我们选择的判断标准出现了误差。

例题:

重点:活动安排、背包问题、最优装载
单源最短路径、哈弗曼编码、最小生成树问题,重点理解贪心策略

第五章回溯法

回溯法的基本思想:

在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯否则,进入该子树,继续按深度优先策略搜索

回溯法解题步骤

  1. 针对所给问题,定义问题的解空间;
  2. 确定易于搜索的解空间结构;
  3. 以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。

用回溯法解题的特征:

在搜索过程中动态产生问题的解空间。问题的解空间树是虚拟的,并不需要在算法运行时构造一棵真正的树结构。在任何时刻,算法只保存从根结点到当前扩展结点的路径

回溯法的算法框架:

递归回溯、子集树与排列树算法框架

影响回溯法的效率因素:

  1. 产生x[k]的时间;
  2. 满足显约束的x[k]值的个数;
  3. 计算约束函数constraint的时间;
  4. 计算上界函数bound的时间;
  5. 满足约束函数和上界函数约束的所有x[k]的个数。

例题(看PPT):

装载问题、n后问题、0-1背包问题、最大团问题、图的m着色问题、旅行售货员问题。
对每一个问题深刻理解以下几点:

  1. 解的表示形式
  2. 解空间表示成什么样的树型结构
  3. 约束条件是什么?
  4. 限界条件是什么(如果有的话)?
  5. 如何构造并输出解。

第六章分支限界法

分支限界法的基本思想:

分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。

分支限界法与回溯法的异同:

1)求解目旳:回溯法旳求解目旳是找出解空间树中满足约束条件旳所有解,而分支限界法旳求解目旳则是找出满足约束条件旳一种解,或是在满足约束条件旳解中找出在某种意义下旳最优解
2)搜索方式旳不同:回溯法以深度优先旳方式搜索解空间树,而分支限界法则以广度优先或以最小耗费优先旳方式搜索解空间树。

分支限界法的实现方式:

队列式和优先队列式

例题:

单源最短路径、装载问题(重点)、0-1背包问题、旅行售货员问题。对于优先队列式分支限界法,重点理解堆元素的优先级怎么定,结点的上界或下界如何确定。

复习题库

选择题

1、二分搜索算法是利用( A )实现的算法。
A、分治策略 B、动态规划法 C、贪心法 D、回溯法
2、下列不是动态规划算法基本步骤的是( A )。
A、找出最优解的性质 B、构造最优解 C、算出最优解 D、定义最优解
3、最大效益优先是( A )的一搜索方式。
A、分支界限法 B、动态规划法 C、贪心法 D、回溯法
5. 回溯法解旅行售货员问题时的解空间树是(B )。
A、子集树 B、排列树 C、深度优先生成树 D、广度优先生成树
6.下列算法中通常以自底向上的方式求解最优解的是( B )。
A、备忘录法 B、动态规划法 C、贪心法 D、回溯法
7、衡量一个算法好坏的标准是(C )。
A 运行速度快 B 占用空间少 C 时间复杂度低 D 代码短
8、以下不可以使用分治法求解的是(D )。
A 棋盘覆盖问题 B 选择问题 C 归并排序 D 0/1背包问题
9. 实现循环赛日程表利用的算法是( A )。
A、分治策略 B、动态规划法 C、贪心法 D、回溯法
11.下面不是分支界限法搜索方式的是( D )。
A、广度优先 B、最小耗费优先 C、最大效益优先 D、深度优先
12.下列算法中通常以深度优先方式系统搜索问题解的是( D )。
A、备忘录法 B、动态规划法 C、贪心法 D、回溯法
13.备忘录方法是那种算法的变形。( B )
A、分治法 B、动态规划法 C、贪心法 D、回溯法
14.哈弗曼编码的贪心算法所需的计算时间为( B )。
A、O(n2n) B、O(nlogn) C、O(2n) D、O(n)
15.分支限界法解最大团问题时,活结点表的组织形式是( B )。
A、最小堆 B、最大堆 C、栈 D、数组
16.最长公共子序列算法利用的算法是( B )。
A、分支界限法 B、动态规划法 C、贪心法 D、回溯法
17.实现棋盘覆盖算法利用的算法是( A )。
A、分治法 B、动态规划法 C、贪心法 D、回溯法
18.下面是贪心算法的基本要素的是( C )。
A、重叠子问题 B、构造最优解 C、贪心选择性质 D、定义最优解
19.回溯法的效率不依赖于下列哪些因素( D )
A.满足显约束的值的个数 B. 计算约束函数的时间
C. 计算限界函数的时间 D. 确定解空间的时间
20.下面哪种函数是回溯法中为避免无效搜索采取的策略( B )
A.递归函数 B.剪枝函数 C。随机数函数 D.搜索函数
21、下面关于NP问题说法正确的是(B )
A NP问题都是不可能解决的问题
B P类问题包含在NP类问题中
C NP完全问题是P类问题的子集
D NP类问题包含在P类问题中
24. (D )是贪心算法与动态规划算法的共同点。
A、重叠子问题 B、构造最优解 C、贪心选择性质 D、最优子结构性质
25. 矩阵连乘问题的算法可由( B)设计实现。
A、分支界限算法 B、动态规划算法 C、贪心算法 D、回溯算法
26. 分支限界法解旅行售货员问题时,活结点表的组织形式是( A )。
A、最小堆 B、最大堆 C、栈 D、数组
27、Strassen矩阵乘法是利用( A )实现的算法。
A、分治策略 B、动态规划法 C、贪心法 D、回溯法
29、使用分治法求解不需要满足的条件是(A )。
A 子问题必须是一样的
B 子问题不能够重复
C 子问题的解可以合并
D 原问题和子问题使用相同的方法解
30、下面问题(B )不能使用贪心法解决。
A 单源最短路径问题 B N皇后问题
C 最小花费生成树问题 D 背包问题
31、下列算法中不能解决0/1背包问题的是(A )
A 贪心法 B 动态规划 C 回溯法 D 分支限界法
34.实现合并排序利用的算法是( A )。
A、分治策略 B、动态规划法 C、贪心法 D、回溯法
35.下列是动态规划算法基本要素的是( D )。
A、定义最优解 B、构造最优解 C、算出最优解 D、子问题重叠性质
37.采用广度优先策略搜索的算法是( A )。
A、分支界限法 B、动态规划法 C、贪心法 D、回溯法
38、合并排序算法是利用( A )实现的算法。
A、分治策略 B、动态规划法 C、贪心法 D、回溯法
40、背包问题的贪心算法所需的计算时间为( B )
A、O(n2n) B、O(nlogn) C、O(2n) D、O(n)
41.实现大整数的乘法是利用的算法( C )。
A、贪心法 B、动态规划法 C、分治策略 D、回溯法
42.0-1背包问题的回溯算法所需的计算时间为( A )
A、O(n2n) B、O(nlogn) C、O(2n) D、O(n)
43.采用最大效益优先搜索方式的算法是( A )。
A、分支界限法 B、动态规划法 C、贪心法 D、回溯法
44.贪心算法与动态规划算法的主要区别是( B )。
A、最优子结构 B、贪心选择性质 C、构造最优解 D、定义最优解
45. 实现最大子段和利用的算法是( B )。
A、分治策略 B、动态规划法 C、贪心法 D、回溯法
46.优先队列式分支限界法选取扩展结点的原则是( C )。
A、先进先出 B、后进先出 C、结点的优先级 D、随机
47.背包问题的贪心算法所需的计算时间为( B )。
A、O(n2n) B、O(nlogn) C、O(2n) D、O(n)
48、广度优先是( A )的一搜索方式。
A、分支界限法 B、动态规划法 C、贪心法 D、回溯法
52. 一个问题可用动态规划算法或贪心算法求解的关键特征是问题的( B )。
A、重叠子问题 B、最优子结构性质 C、贪心选择性质 D、定义最优解
53.采用贪心算法的最优装载问题的主要计算量在于将集装箱依其重量从小到大排序,故算法的时间复杂度为 ( B ) 。
A、O(n2n) B、O(nlogn) C、O(2n) D、O(n)
54. 以深度优先方式系统搜索问题解的算法称为 ( D ) 。
A、分支界限算法 B、概率算法 C、贪心算法 D、回溯算法
55. 实现最长公共子序列利用的算法是( B )。
A、分治策略 B、动态规划法 C、贪心法 D、回溯法

填空题

1.算法的复杂性有 时间 复杂性和 空间 复杂性之分。
2、程序是 算法 用某种程序设计语言的具体实现。
3、算法的“确定性”指的是组成算法的每条 指令 是清晰的,无歧义的。
4.矩阵连乘问题的算法可由 动态规划 设计实现。
6、算法是指解决问题的 一种方法一个过程
7、从分治法的一般设计模式可以看出,用它设计出的程序一般是 递归算法
8、问题的 最优子结构性质 是该问题可用动态规划算法或贪心算法求解的关键特征。
9、以深度优先方式系统搜索问题解的算法称为 回溯法
11、计算一个算法时间复杂度通常可以计算 循环次数基本操作的频率 或计算步。
14、解决0/1背包问题可以使用动态规划、回溯法和分支限界法,其中不需要排序的是 动态规划 ,需要排序的是 回溯法分支限界法
15、使用回溯法进行状态空间树裁剪分支时一般有两个标准:约束条件和目标函数的界,N皇后问题和0/1背包问题正好是两种不同的类型,其中同时使用约束条件和目标函数的界进行裁剪的是 0/1背包问题 ,只使用约束条件进行裁剪的是 N皇后问题
16、 贪心选择性质 是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。
17、矩阵连乘问题的算法可由 动态规划 设计实现。
19.贪心算法的基本要素是 贪心选择 质和 最优子结构 性质 。
21. 动态规划算法的基本思想是将待求解问题分解成若干 子问题 ,先求解 子问题 ,然后从这些 子问题 的解得到原问题的解。
22.算法是由若干条指令组成的有穷序列,且要满足输入输出确定性有限性 四条性质。
23、大整数乘积算法是用 分治法 来设计的。
24、以广度优先或以最小耗费方式搜索问题解的算法称为 分支限界法
26、 贪心选择性质 是贪心算法可行的第一个基本要素,也是贪心算法与动态规划算法的主要区别。
27.快速排序算法是基于 分治策略 的一种排序算法。
28.动态规划算法的两个基本要素是. 最优子结构 性质和 重叠子问题 性质 。
30.回溯法是一种既带有 系统性 又带有 跳跃性 的搜索算法。
31.分支限界法主要有 队列式(FIFO) 分支限界法和 优先队列式 分支限界法。
32.分支限界法是一种既带有 系统性 又带有 跳跃性 的搜索算法。
33.回溯法搜索解空间树时,常用的两种剪枝函数为 约束函数限界函数
34.任何可用计算机求解的问题所需的时间都与其 规模 有关。
35.快速排序算法的性能取决于 划分的对称性

算法填空

1.背包问题的贪心算法

void Knapsack(int n, float M, float v[], float w[], float x[])
{
      Sort(n, v, w);//排序
      int i;
      for (i = 1; i <= n; i++) x[i] = 0;//不选这个物品
      Float c = M;//设置背包剩余容量
      for (i = 1; i <= n; i++)//开始遍历物品
    	{
          if (w[i] > c) break;//如果物品的重量大于剩余背包容量,跳出循环
          x[i] = 1;//否则改变物品状态为1 表示已经选择
          c - = w[i];//背包剩余容量改变 
    	}
   if (i <= n) x[i] = c / w[i];//如果没有装完物品的话,能装多少装多少
}
 

2.最大子段和 动态规划算法

int MaxSum(int n, int a[])
{
    int sum = 0, b = 0; //sum用来表示最大值 b用来当做目前的子段和
    for (int j = 1;j <= n;j++)
    {
        if(b > 0) b += a[j]; //如果b大于0,那么就加上当前的 
        else b = a[j];//否则就等于当前的
        if (b > sum)//如果b比sum大的话 那么sum就赋值为b
            sum = b;
    }
    return sum;
}   

3.贪心算法求装载问题

template <class Type>
void Loading(int x[], Type w[], Type c, int n)
{
    int *t = new int[n + 1];
    Sort(w, t, n) 
    for (int i = 1; i <= n; i++) x[i] = 0;
    for (int i = 1; i <= n && w[t[i]] <= c; i++)
    {
        x[t[i]] = 1;
        c -= w[t[i]];
    }
}

4.贪心算法求活动安排问题

template <class Type>
void GreedySelector(int n, Type s[], Type f[], bool A[])
{
    A[1] = true;
    int j = 1;
    for (int i = 2; i <= n; i++)
    {
        if (s[i] >= f[j])//如果开始时间大于上一个的结束时间
        {
            A[i] = true;//选择这个活动
            j = i;//更新上一个活动的标记
        }
        else
            A[i] = false;//不选这个活动
    }
}

5.快速排序

核心思想是二分

template <class Type>
void QuickSort(Type a[], int p, int r)
{
    if (p < r)
    {
        Int q = Partition(a, p, r);
        QuickSort(a, p, q - 1); // 对左半段排序
        QuickSort(a, q + 1, r); // 对右半段排序
    }
}

6.排列问题

Template<class Type> void perm(Type list[], int k, int m)
{
    if (k == m)
    { // 只剩下一个元素 直接输出列表元素0~m
        for (int i = 0; i <= m; i++)
            cout << list[i];
        cout << endl;
    }
    else // 还有多个元素待排列,递归产生排列
        for (int i = k; i <= m; i++)//从k到m
        {
            swap(list[k],list[i]);//交换k i元素
            perm(list, k + 1, m);//排列 k+1~m
            swap(list[k], list[i]);//再换回来
        }
}

7.用回溯法搜索子集树的算法为:

void backtrack(int t)
{
    if (t > n)
        output(x);//大于节点数了,直接输出x
    else
        for (int i = 0; i <= 1; i++)
        {
            x[t] = i;
            if (constraint(t) && bound(t))
                backtrack(t + 1);
        }
}

简答题

1.分治法的基本思想:

将一个规模为n的问题分解为k个规模较小的子问题,这些子问题互相独立且与原问题相同。递归地解这些子问题,然后将各个子问题的解合并得到原问题的解。

2.设计动态规划算法的主要步骤为:

(1)找出最优解的性质,并刻画其结构特征。(2)递归地定义最优值。
(3)以自底向上的方式计算出最优值。(4)根据计算最优值时得到的信息,构造最优解。

3. 分治法与动态规划法异同

相同点是:将待求解的问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题的解。
不同点是:适合于用动态规划法求解的问题,经分解得到的子问题往往不是互相独立的。而用分治法求解的问题,经分解得到的子问题往往是互相独立的。

4. 分支限界法与回溯法异同

相同点:都是一种在问题的解空间树T中搜索问题解的算法。
不同点:(1)求解目标不同(2)搜索方式不同(3)对扩展结点的扩展方式不同(4)存储空间的要求不同。

5.贪心算法与动态规划算法的主要区别

所谓贪心选择性质是指所求问题的整体最优解可以通过一系列局部最优的选择,即贪心选择来达到。这是利用贪心算法求解最优解的第一个基本要素,也是贪心算法与动态规划算法的主要区别。
共同点:
求解的问题都具有最优子结构性质
差异点:
动态规划算法通常以自底向上的方式解各子问题,而贪心算法则通常以自顶向下的方式进行,以迭代的方式作出相继的贪心选择,每做一次贪心选择就将所求问题简化为规模更小的子问题。

6. 分治法所能解决的问题一般具有的几个特征是:

(1)该问题的规模缩小到一定的程度就可以容易地解决;
(2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;
(3)利用该问题分解出的子问题的解可以合并为该问题的解;
(4)原问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子问题。

7. 用分支限界法设计算法的步骤是:

(1)针对所给问题,定义问题的解空间(对解进行编码)(2)确定易于搜索的解空间结构(按树或图组织解);(3)以广度优先或以最小耗费(最大收益)优先的方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。

8. 常见的两种分支限界法的算法框架

(1)队列式(FIFO)分支限界法:按照队列先进先出原则选取下一个节点为扩展节点。
(2)优先队列式分支限界法:按照优先队列中规定的优先级选取优先级最高的节点成为当前扩展节点。

9. 回溯法中常见的两类典型的解空间树:

子集树:当所给的问题是从n个元素的集合S中找出满足某种性质的子集时,相应的解空间树称为子集树。这类子集树通常有2n个叶结点,遍历子集树需O(2n)计算时间 。
排列树:当所给的问题是确定n个元素满足某种性质的排列时,相应的解空间树称为排列树。这类排列树通常有n!个叶结点。遍历排列树需要O(n!)计算时间。

10. 分支限界法的搜索策略是:

在扩展结点处,先生成其所有的儿子结点(分支),然后再从当前的活结点表中选择下一个扩展结点。为了有效地选择下一扩展结点,加速搜索的进程,在每一个活结点处,计算一个函数值(限界),并根据函数值,从当前活结点表中选择一个最有利的结点作为扩展结点,使搜索朝着解空间上有最优解的分支推进,以便尽快地找出一个最优解。

11、回溯法的基本思想

是在一棵含有问题全部可能解的状态空间树上进行深度优先搜索,解为叶子结点。搜索过程中,每到达一个结点时,则判断该结点为根的子树是否含有问题的解,如果可以确定该子树中不含有问题的解,则放弃对该子树的搜索,退回到上层父结点,继续下一步深度优先搜索过程。在回溯法中,并不是先构造出整棵状态空间树,再进行搜索,而是在搜索过程,逐步构造出状态空间树,即边搜索,边构造。

算法设计题

  1. 给定已按升序排好序的n个元素a[0:n-1],现要在这n个元素中找出一特定元素x,返回其在数组中的位置,如果未找到返回-1。
    写出二分搜索的算法,并分析其时间复杂度。
template <class Type>
int BinarySearch(Type a[], const Type &x, int n)
{ // 在a[0:n]中搜索x,找到x时返回其在数组中的位置,否则返回-1
    int left = 0;
    int right = n - 1;
    while(left <= right)
    {
        int middle = (left + right) / 2;//找到中点
        if (x == a[middle])//如果找到了 返回
            return middle;
        if (x > a[middle])//如果大于 那就在右边找
            left = middle + 1;
        else //如果小于 那就在左边找
            right = middle - 1;
    }
    Return - 1;//没找到 返回-1
}

时间复杂性为O(logn)

  1. 利用分治算法写出合并排序的算法,并分析其时间复杂度
void MergeSort(Type a[], int left, int right)
{
    if (left < right)
    {                               // 至少有2个元素
        int i = (left + right) / 2; // 取中点
        mergeSort(a, left, i);//左侧合并排序
        mergeSort(a, i + 1, right);//右侧合并排序
        merge(a, b, left, i, right); // 合并到数组b
        copy(a, b, left, right);     // 复制回数组a
    }
}

算法在最坏情况下的时间复杂度为O(nlogn)。

3.N皇后回溯法

bool Queen::Place(int k)
{ // 检查x[k]位置是否合法
    for (int j = 1; j < k; j++)
        if ((abs(k - j) == abs(x[j] - x[k])) || (x[j] == x[k]))
            return false;
    return true;
}

void Queen::Backtrack(int t)
{
    if (t > n)
        sum++;
    else
        for (int i = 1; i <= n; i++)
        {
            x[t] = i;
            if (约束函数)
                Backtrack(t + 1);
        }
}

4.最大团问题 回溯法

void Clique::Backtrack(int i) // 计算最大团
{
    if (i > n)
    { // 到达叶结点
        for (int j = 1; j <= n; j++)
        	bestx[j] = x[j];
        bestn = cn;
        return;
    }
    // 检查顶点 i 与当前团的连接
    int OK = 1;
    for (int j = 1; j < i; j++)
        if (x[j] && a[i][j] == 0)
        { // i与j不相连
            OK = 0;
            break;
        }
    if (OK)
    { // 进入左子树
        x[i] = 1;
        cn++;
        Backtrack(i + 1);
        x[i] = 0;
        cn--;
    }
    if (cn + n - i > bestn)
    { // 进入右子树
        x[i] = 0;
        Backtrack(i + 1);
    }
}

5.最长公共子序列问题

// 参数:x字符串长度为m y字符串长度为n
void LCSLength(char x[], char y[], int m, int n)
{
    /* 计算最长公共子序列的长度 */
    int L[m][n], i,j;
    for (i = 0; i <= m; i++)
        L[i][0] = 0;
    for (i = 0; i <= n; i++)
        L[0][i] = 0;
    for (i = 1; i <= m; i++)
    {
        for (j = 1; j <= n; j++)
        {
            if (x[i] == y[j])
                L[i][j] = L[i - 1][j - 1] + 1;
            else if (L[i - 1][j] >= L[i][j - 1])
                L[i][j] = L[i - 1][j];
            else
                L[i][j] = L[i][j - 1];
        }
    }
    return L[m][n];
}

6.分别用贪心算法、动态规划法、回溯法设计0-1背包问题。要求:说明所使用的算法策略;写出算法实现的主要步骤;分析算法的时间。
(1)贪心算法 O(nlog(n))
首先计算每种物品单位重量的价值Vi/Wi,然后,依贪心选择策略,将尽可能多的单位重量价值最高的物品装入背包。若将这种物品全部装入背包后,背包内的物品总重量未超过C,则选择单位重量价值次高的物品并尽可能多地装入背包。依此策略一直地进行下去,直到背包装满为止。

void Knapsack(int n, float M, float v[], float w[], float x[])
{
    sort(n, v, w);
    int i;
    for (i = 1; i <= n; i++) x[i] = 0;
    float c = M;
    for (i = 1; i <= n; i++)
    {
        if (w[i] > c) break;
        x[i] = 1;
        c -= w[i];
    }
    if (i <= n)
        x[i] = c / w[i];
}

(2)动态规划法 O(nc)
m(i,j)是背包容量为j,可选择物品为i,i+1,…,n时0-1背包问题的最优值。由0-1背包问题的最优子结构性质,可以建立计算m(i,j)的递归式如下。

在这里插入图片描述

void KnapSack(int v[], int w[], int c, int n, int m[][11])
{
    int jMax = min(w[n] - 1, c);
    for (j = 0; j <= jMax; j++) /*m(n,j)=0   0=<j<w[n]*/
        m[n][j] = 0;
    for (j = w[n]; j <= c; j++) /*m(n,j)=v[n]   j>=w[n]*/
        m[n][j] = v[n];
    for (i = n - 1; i > 1; i--)
    {
        int jMax = min(w[i] - 1, c);
        for (j = 0; j <= jMax; j++) /*m(i,j)=m(i+1,j)   0=<j<w[i]*/
            m[i][j] = m[i + 1][j];
        for (j = w[i]; j <= c; j++) /*m(n,j)=v[n]   j>=w[n]*/
            m[i][j] = max(m[i + 1][j], m[i + 1][j - w[i]] + v[i]);
    }
    m[1][c] = m[2][c];
    if (c >= w[1])
        m[1][c] = max(m[1][c], m[2][c - w[1]] + v[1]);
}

(3)回溯法 O(2n)
cw:当前重量 cp:当前价值 bestp:当前最优值

void backtrack(int i)
// 回溯法 i初值1
{
    if (i > n) // 到达叶结点
    {
        bestp = cp;
        return;
    }
    if (cw + w[i] <= c) // 搜索左子树
    {
        cw += w[i];
        Cp += p[i];
        backtrack(i + 1);
        cw -= w[i];
        cp -= p[i];
    }
    if (Bound(i + 1) > bestp)
        // 搜索右子树
        backtrack(i + 1);
      
}

7.通过键盘输入一个高精度的正整数n(n的有效位数≤240),去掉其中任意s个数字后,剩下的数字按原左右次序将组成一个新的正整数。编程对给定的n 和s,寻找一种方案,使得剩下的数字组成的新数最小。
【样例输入】
178543
S=4
【样例输出】
13
为了尽可能地逼近目标,我们选取的贪心策略为:每一步总是选择一个使剩下的数最小的数字删去,即按高位到低位的顺序搜索,若各位数字递增,则删除最后一个数字,否则删除第一个递减区间的首字符。然后回到串首,按上述规则再删除下一个数字。重复以上过程s次,剩下的数字串便是问题的解了。
具体算法如下:

输入s, n;
while( s > 0{
    i = 1; // 从串首开始找
    while (i < length(n)&&(n[i] < n[i + 1])
        {
            i++;
        }
    delete (n, i, 1); // 删除字符串n的第i个字符
    s--;
}
while (length(n) > 1)&&(n[1] =0) delete(n, 1, 1); // 删去串首可能产生的无用零
输出n;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/671340.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mine vpn

client remote ‘whvpn.deepin.com’ 1194 auth-user-pass dev tun proto tcp nobind auth-nocache script-security 2 persist-key persist-tun user nm-openvpn group nm-openvpn -----BEGIN CERTIFICATE----- MIIDPDCCAiSgAwIBAgIUUTvTCz6BndUDTIVTBxpKL19mEMkwDQYJKoZIhvcN…

JAVA开发(spring RestFull风格Feign使用总结)

现在大多数的springboot都是使用RestFull风格的接口&#xff0c;是Feign进行远程调用。 一、Feign介绍&#xff1a; Feign是Spring Cloud Netflix组件中的一个轻量级RESTFULL的http服务客户端&#xff0c;实现了负载均衡和Rest调用的开源框架&#xff0c;封装了Ribbon和RestTe…

使用谷歌 Chrome 浏览器禁用网页 JavaScript

使用谷歌 Chrome 浏览器禁用网页 JavaScript 文章目录 使用谷歌 Chrome 浏览器禁用网页 JavaScriptI - 概述1.1 - JavaScript 的功能1.2 - 为何要禁用 JavaScript II - 禁用 JavaScript 的方式2.1 - Chrome 调试工具2.2 - Chrome 黑名单 I - 概述 1.1 - JavaScript 的功能 Web…

Fegin 中统一处理调用的结果

背景 项目中&#xff0c;微服务环境下&#xff0c;有很多时候&#xff0c;都需要调用其他服务&#xff0c;而且其他服务基本上都有一个骨架类(如下图)&#xff0c;为了不用每次调用都去判断是否成功&#xff0c;所以需要统一处理接口返回的结果 思考 跟踪代码发现&#xff0c;…

Seata Saga 模式理论学习、生产级使用示例搭建及注意事项(二) | Spring Cloud58

一、前言 通过以下系列章节&#xff1a; docker-compose 实现Seata Server高可用部署 | Spring Cloud 51 Seata AT 模式理论学习、事务隔离及部分源码解析 | Spring Cloud 52 Spring Boot集成Seata利用AT模式分布式事务示例 | Spring Cloud 53 Seata XA 模式理论学习、使用…

Dubbo服务发现原理

一、Dubbo服务发现设计 Dubbo提供的是一种Client-Based的服务发现机制&#xff0c;依赖第三方注册中心组件来协调服务发现过程&#xff0c;支持常用的注册中心如Nacos、Connsul、Zookeeper等 Dubbo服务发现机制的基本工作原理图&#xff1a; 服务发现包含提供者、消费者和注册…

MySQL 被 PG 干翻了。。

出品 | OSC开源社区&#xff08;ID&#xff1a;oschina2013) Stack Overflow 发布了 2023 年开发者调查报告&#xff0c;据称共计超过 9 万名开发者参与了此次调查。 完整报告包含了受访开发者画像&#xff0c;以及关于开发技术、AI、职业、社区等方面的内容。本文主要介绍关于…

ICC2: 工具是如何控制局部利用率的?

分析congestion map时不难发现,route congestion高的地方局部利用率往往要比周围低,这时疑问就来了,既然standard cell的分布不是均匀的,那局部再降一降彻底解决congestion问题不好嘛?工具是如何控制这种congestion driven的行为的呢? 在place_opt以及clock_opt的log里都…

Apache Atlas高级搜索语法示例

from hive_table;hive_table from hive_table where name xxx or name yyy from hive_table where name ["xxx", "yyy"] from hive_table where name LIKE *_xxx hive_db where name like "???dm?*" hive_column where table.name …

Dcat Admin 2 集成富文本编辑器 wangEditor 5

由于默认的 TinyMCE 个人不是很喜欢&#xff0c;所以替换成国产的富文本编辑器 wangEditor Dcat Admin 文档示例&#xff1a;集成富文本编辑器 wangEditor 但是官方的示例是针对 wangEditor 4 编写的&#xff0c;这里仅指出对版本 5 的差异部分 获取文件 将以下三个文件保存…

快码住! 结构体内存对齐(计算结构体大小) 干货满满!

文章目录 结构体内存对齐规则结构体大小计算为什么存在内存对齐&#xff1f;设计结构体的技巧如何修改默认对齐数&#xff1f; 结构体内存对齐规则 我们知道&#xff0c;整型变量有自己的大小&#xff0c;浮点型变量有自己的大小&#xff0c;数组也有自己的大小&#xff0c;那…

血流动力学与血压(一)--平均动脉压

平均动脉压 在血管血流动力学研究中&#xff0c;心血管系统通常被认为是一个简单的液压回路&#xff0c;由泵&#xff08;心脏&#xff09;组成&#xff0c;泵&#xff08;心脏&#xff09;有节奏地活动&#xff08;收缩 --> 舒张 --> 收缩 --> 舒张 --> 收缩…&am…

中国一重集中采购平台的建设经历和亮点

中国一重前身为第一重型机器厂&#xff0c;是“一五”期间建设156项重点工程项目之一&#xff0c;始建于1954年&#xff0c;是中央管理的涉及国家安全和国民经济命脉的国有重要骨干企业之一&#xff0c;是国家创新型试点企业、国家高新技术企业&#xff0c;拥有国家级企业技术中…

java 校园管理系统Myeclipse开发mysql数据库web结构jsp编程计算机网页项目

一、源码特点 JSP 校园管理系统 是一套完善的系统源码&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;以及相应配套的设计文档&#xff0c;系统主要采用B/S模式开发。 研究的基本内容是基于Web的校园管理系统&…

访问不到阿里云服务器端口

这里前台在主机上 然后访问服务器上的node后台 一直访问不到 不能连入阿里云服务器后台 连不上公网ip端口 解决方案 登录阿里云 进入云服务器 2、管理控制台 3、网络与安全——>安全组 4、安全组里面点击配置规则 5、手动添加 即可

《项目实战》构建SpringCloud alibaba项目(三、构建服务方子工程store-user-service)

系列文章目录 构建SpringCloud alibaba项目&#xff08;一、构建父工程、公共库、网关&#xff09; 构建SpringCloud alibaba项目&#xff08;二、构建微服务鉴权子工程store-authority-service&#xff09; 构建SpringCloud alibaba项目&#xff08;三、构建服务方子工程stor…

python学习——NumPy数值计算基础

目录 NumPy数值计算基础1.array创建数组及其属性2.其他创建方式3.数据类型及其转换4.生成随机数5.数组的索引和切片6.改变数组形态【案例】两个国家的数据方法一起来研究分析&#xff0c;同时保留国家的信息&#xff08;每条数据的国家来源&#xff09;&#xff0c;应该怎么办 …

《网络安全0-100》单钥加密体制

单钥加密体制 DES算法 DES属于对称密码算法中的分组加密(块加密)&#xff0c;和流密码相对应。DES算法将明文分为若干个64位块(不足补充)&#xff0c;秘钥为56位(8位校验位)。DES算法流程图如下 接下来&#xff0c;进行DES算法关键步骤的逐步解析&#xff1a; IP置换 IP置换…

Python学习——数据分组统计、分组运算及透视

目录 1 数据分组统计 groupby1.1 按照单列进行分组统计df.groupby(列名).count()1.2 按照多列进行分组统计 df.groupby([列名1,列名2]).count()1.3 分组填充缺失值 df.groupby(需填充列名).apply(lambda x:x.fillna(x.mean())) 2 分组运算 agg2.1 传入标准函数 df.groupby(班级…

机器学习之KNN(K近邻)算法

1 KNN算法介绍 KNN算法又叫做K近邻算法&#xff0c;是众多机器学习算法里面最基础入门的算法。KNN算法是最简单的分类算法之一&#xff0c;同时&#xff0c;它也是最常用的分类算法之一。KNN算法是有监督学习中的分类算法&#xff0c;它看起来和Kmeans相似&#xff08;Kmeans是…