算法分析与设计-期末复习-第五章+第六章+填空题+写出递归方程问题

本文详细介绍了回溯法的核心思想、解题步骤以及影响效率的因素,同时也对比了与分支限界法的区别。通过例题展示了如何在0-1背包、N皇后等经典问题中应用这些方法。后续部分讨论了分支限界法的基本概念和实现策略,以及算法填空题涉及的排序、背包问题和哈夫曼编码等知识点。
摘要由CSDN通过智能技术生成

注意事项:

序号有点问题,影响不大,内容都是各种资料整合和我自己归纳总结的,不喜勿喷,感觉扔回收站可惜了,所以分享出来,能有帮上你的忙就最好不过了,更多复习资料,可以去看我的合集。

五、回溯法:装载问题,待处理作业调度,符号三角形,n 皇后,0-1 背包,最大团,图的 m 着色,旅行售货员,圆排列,电路板排列,连续油资

回溯法的基本思想:

在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。

算法搜索至解空间树的任意一点时,先判断该结点是否包含问题的解。

如果肯定不包含,则跳过对该结点为根的子树的搜索,逐层向其祖先结点回溯;

否则,进入该子树,继续按深度优先策略搜索。

回溯法解题步骤

针对所给问题,定义问题的解空间;

确定易于搜索的解空间结构;

以深度优先方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。

用回溯法解题的特征:

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

回溯法的算法框架:

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

影响回溯法的效率因素:

产生x[k]的时间;

满足显约束的x[k]值的个数

计算约束函数constraint的时间

计算上界函数bound的时间

满足约束函数上界函数约束的所有x[k]的个数

例题:

  1. 避免无效~剪枝函数
  2. 0-1 背包~n2n
  3. 售货员~排列树~TSP
  4. 树裁剪分支俩标准(剪枝函数):约束函数和限界函数,只用约束条件:N 皇后问题,俩都用:0-1 背包问题
  5. 回溯~系统性又跳跃性的搜索方法~分支限界

六、分支限界法:单源最短路径,装载,布线,0-1 背包,最大团,旅行售货员,电路板排列,批处理作业调度

分支限界法的基本思想:

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

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

1)求解目旳:回溯法旳求解目旳是找出解空间树中满足约束条件旳所有解,而分支限界法旳求解目旳则是找出满足约束条件旳一种解,或是在满足约束条件旳解中找出在某种意义下旳最优解。

2)搜索方式旳不同:回溯法以深度优先旳方式搜索解空间树,而分支限界法则以广度优先或以最小耗费优先旳方式搜索解空间树。

用分支限界法设计算法的步骤/策略:

(1)针对所给问题,定义问题的解空间(对解进行编码)

(2)确定易于搜索的解空间结构(按树或图组织解);

(3)以广度优先或以最小耗费(最大收益)优先的方式搜索解空间,并在搜索过程中用剪枝函数避免无效搜索。

分支限界法的实现方式:

队列式:按照队列先进先出(FIFO)原则选取下一个节点为扩展节点。

优先队列式:按照 优先队列中规定的优先级 选取 优先级最高的节点 成为 当前扩展节点。

例题:

  1. 最大团~活节点表~最大堆
  2. 售货员~活节点表~最小堆
  3. NP 包含 P
  4. 优先队列~选取扩展结点~ 结点的优先级

算法填空题:

1. 归并排序:

2. 快速排序:

3. 贪心,动态,回溯 求 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);
      
}

4. 哈夫曼编码过程:

写出递归方程问题:

1. 0-1 背包:

2. 最长公共子序列:

3. 主定理解递归:T(n)=4T(n/2)+n

:由递归方程可得,a=4,b=2 且 f(n)=n。因此,

4. 递归树解:T(n)=2T(n/2)+n-1

  • 17
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值