NJUPT算法分析与设计期末考试202.12.1

这篇具有很好参考价值的文章主要介绍了NJUPT算法分析与设计期末考试202.12.1。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


用书:计算机算法设计与分析(第五版)
判断10题30分
简答5题30分
算法设计4*10=40分

判断

1.程序、算法、软件是不完全等价的。
2.最优化问题不是都可以用动态规划来求解,使用动态规划要满足(子问题间有依赖关系;有最优子结构)。
3.分治策略是先把复杂的问题自顶向下求解,然后自底向上合并,不一定要用递归,用迭代也可以。
4.动态规划能求解的问题,贪心策略不一定能求解,反之也不行。(如0-1背包问题可以用动态规划但不能用贪心;背包问题可以用贪心但不能用递归)。
5.两个序列的公共子序列和最长公共子序列都不唯一。
6.棋盘覆盖问题8*8的棋盘用(64-1)/3=21块骨牌。
7.哈夫曼算法是贪心算法,每次选择频率最高的两个节点合并成子树。
8.不同的排序算法针对不同实例,速度效率不一样。
9.常用的时间复杂度。

简答

1.算法是什么?算法的时间复杂度是什么?衡量的原则,标准,工具

(PPT ch1)

  • 算法的定义:算法是对特定问题求解步骤的一种描述,它是由若干指令组成的有穷序列,特性(输入、输出、有穷、确定、可行)
  • 时间算法复杂度:是对算法执行所需的时间的一种度量;
  • 原则标准:统一机器性能,分析最坏情况
  • 工具:渐进分析方法:忽略T(n)的系数与低阶项,仅关注高阶项;

2.分支限界法扩展活节点的方式有哪两种,有什么差别?

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

3.回溯法搜索子集树,排列树的算法。P124

http://wjhsh.net/xymqx-p-3702921.html

回溯法搜索子集树

//回溯法搜索子集树
void Backtrack(int t){
{
    if(t>n)
        output(x);
    else
    {
        for(int i=0;i<=1;i++)   //子集树只考虑取或者不取,所以解向量只有0或1;
        {
            x[t]=i;   
            if(Constraint(t)&&Bound(t))
                Backtrack(t+1);
        }
    }
}

回溯法搜索排列树

//回溯法搜索排列树
void Backtrack(int t){
{
    if(t>n)
        output(x);
    else
    {
        for(int i=t;i<=n;i++)
        {
            Swap(x[t],x[i]);    //把当前递归层的元素依次和其他元素交换
            if(Constraint(t)&&Bound(t))
                Backtrack(t+1);  //进入下一层递归
            Swap(x[t],x[i]);   //回溯时候恢复之前的交换
        }
    }
}

4.剪枝策略:什么是约束函数,什么是限界函数,区别是什么?

约束函数:在扩展节点处剪去不满足约束的子树
限界函数:用限界函数剪去不能得到最优解的子树
都是剪去不必要搜索的子树,约束函数剪去的是无解的子树,而限界函数剪去的是得不到最优解的子树。

5.递归分治策略和动态规划策略的相同和不同

相同:都是把大问题转化为子问题来解决
不同:递归分治的子问题相互独立,动态规划的子问题是相互依赖的,有最优子结构

算法设计

一、递归+分治(修改的二分搜索问题)

问题描述

改写二分搜索算法,使得当搜索元素x不在数组中时,返回小于x的最大元素位置i和大于x的元素位置j。当搜索元素在数组中时,i和j相同,均为x在数组中的位置。

1.二分搜索的基本思想

二分搜索方法充分利用了元素间的次序关系,采用分治策略,可以在最坏情况下用O(logn)时间完成搜索任务,将n个元素分成个数大致相同的两半,取a[n/2]与x进行比较,若x=a[n/2],则找到x,算法终止;x=a[n/2],则只在数组左半部递归的搜索;若x>a[n/2],则只在数组右半部递归的搜索。

2.实现

int Binary_Search(int a[],int length, int x)       //a是搜索数组,x为搜索元素
{
	int i = 0, j = 0; //用来输出结果
	int flag = -1;//标志位
	int high = length - 1; // 数组的右边界
	int mid = 0;  //中间值的下标
	int low = 0; //数组的左边界
 
	while (low <= high)
	{
		mid = (low + high) / 2;
		if (a[mid] == x)
		{
			flag = middle;
		}
		if (a[mid] < x)
		{
			low = mid + 1;
		}
		else
		{
			top = mid - 1;
		}
	}
	if (flag == -1)
	{
		i = high;
		j = low;
	}
	else
	{
		i = j = flag ;
	}
    cout<<i<<j;
	return 0;
}

二.DP(最大字段和问题)

问题描述

NJUPT算法分析与设计期末考试202.12.1

1.最优子结构递推方程

NJUPT算法分析与设计期末考试202.12.1

2.算法框架

void dp(int D[],int X[],int R[],n)
{ //X[i]存储第i个数字的值,D[i]表示以x[i]为开头的最大字段和的值;R[]
    D[n]=X[n]; //最后一位开头的最长子段和只能是本身
    R[n]=n;   //最后一位的右端点只能是n
    for(int i=n-1;i>=n;i--)
    {   //最后一个位置的数字作为初值,从倒数第二个位置开始从后向前递推
        if(D[i+1]>0) 
            D[i]=X[i]+D[i+1]; //如果以i+1位置开头的最大字段和大于0,那么以i位置开头最大字段和就是当前位置的数值+后面的最大字段和的值。
        else{
            D[i]=X[i]; //如果以i+1位置开头的最大字段和小于0;
            R[i]=i; //此时最大字段和的右端就是i本身
            }
    }
}

void MaxSum(int D[],int R[]}
{
    S_max=D[1] //先假设以第一个数字开头的最大字段和为全局最大字段和
    for(int i=2;i<=n;i++)
    {
        if(S_max<D[i])
        {
            l=i;
            r=R[i];
        }
    }
    cout<<"最大字段和从位置"<<l<<"到位置"<<r<<"其值为"<<D[l];
}     
        

3.实例推导

NJUPT算法分析与设计期末考试202.12.1

4.时间复杂度

O(n)

三.贪心(最优装载问题)

问题描述

NJUPT算法分析与设计期末考试202.12.1

1.数学模型

NJUPT算法分析与设计期末考试202.12.1

2.算法框架

void Loading(int x[],  Type w[], Type c, int n)
{
        int *t = new int [n+1];   //动态数组t用来存放排序后的货物
        Sort(w, t, n);    //将集装箱按重量把数组w非减排序存放到数组t中
        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;   //决策变量的对应位置置为1
                        c -= w[t[i]]; //更新当前的荷载量
        } //在剩余集装箱中选择最轻的装船,直至超重
}

3.时间复杂度

O(nlogn) 主要来自把货物按重量排序的算法sort()

4.正确性分析NJUPT算法分析与设计期末考试202.12.1NJUPT算法分析与设计期末考试202.12.1

四.回溯和分支限界(旅行商问题)

1.解空间是子集树还是排列树?

答:排列树,因为每个城市都要访问。

2.回溯法求解的过程

NJUPT算法分析与设计期末考试202.12.1
NJUPT算法分析与设计期末考试202.12.1
NJUPT算法分析与设计期末考试202.12.1
NJUPT算法分析与设计期末考试202.12.1
NJUPT算法分析与设计期末考试202.12.1

//旅行商问题回溯算法的实现
//形参t是回溯的深度,从2开始
void Backtrack(int t)
{
  //到达叶子结点的父结点
  if(t==n)
  {
    if(a[x[n-1]][x[n]]!= NoEdge && a[x[n]][1]!= NoEdge && 
      (cc + a[x[n-1]][x[n]]+a[x[n]][1]<bestc||bestc== NoEdge))
    {
      for(int i=1; i<=n; i++)
        bestx[i] = x[i];
      bestc = cc + a[x[n-1]][x[n]] + a[x[n]][1];
    }
    return;
  }
else 
  {
    for(int i=t; i<=n; i++)
    {
      if(a[x[t-1]][x[i]]!= NoEdge &&
        (cc + a[x[t-1]][x[i]]< bestc||bestc == NoEdge))
      {
        swap(x[t],x[i]);
        cc += a[x[t-1]][x[t]];
        Backtrack(t+1);
        cc -= a[x[t-1]][x[t]];
        swap(x[t],x[i]);
      }
    }
  }
}
 

3.分支限界法求解的过程

NJUPT算法分析与设计期末考试202.12.1
NJUPT算法分析与设计期末考试202.12.1
NJUPT算法分析与设计期末考试202.12.1
NJUPT算法分析与设计期末考试202.12.1文章来源地址https://www.toymoban.com/news/detail-467150.html

//旅行商问题分支限界法的实现
template <class Type>
Type Traveling<Type>::BBTSP(int *v, Type **G, int tn, Type tNoEdge)
{
    priority_queue<MinHeapNode<Type> > pq;
    MinHeapNode<Type> E, N;
    Type bestc, cc, rcost, MinSum, *MinOut, b;
    int i, j;
 
    a = G;
    n = tn;
    NoEdge = tNoEdge;
    MinSum = 0;                                             //最小出边费用和
    MinOut = new Type[n+1];                                 //计算MinOut[i]=顶点i的最小出边费用
    for(i = 1; i <= n; i++)
    {
        MinOut[i] = NoEdge;
        for(j = 1; j <= n; j++)
            if(a[i][j] != NoEdge && (a[i][j] < MinOut[i] || MinOut[i] == NoEdge))
                MinOut[i] = a[i][j];
        if(MinOut[i] == NoEdge)                             //无回路
            return NoEdge;
        MinSum += MinOut[i];
    }
    //初始化
    E.s = 0;
    E.cc = 0;
    E.rcost = MinSum;
    E.x = new int[n];
    for(i = 0; i < n; i++)
        E.x[i] = i+1;
    bestc = NoEdge;
    //搜索排列空间树
    while(E.s < n-1)                                        //非叶结点
    {
        if(E.s == n-2)                                      //当前扩展结点是叶结点的父结点 再加2条边构成回路
        {                                                   //所构成回路是否优于当前最优解
            if(a[E.x[n-2]][E.x[n-1]] != NoEdge && a[E.x[n-1]][1] != NoEdge &&
            (E.cc+a[E.x[n-2]][E.x[n-1]]+a[E.x[n-1]][1] < bestc || bestc==NoEdge))
            {
                //费用更小的路
                bestc = E.cc + a[E.x[n-2]][E.x[n-1]] + a[E.x[n-1]][1];
                E.cc = bestc;
                E.lcost = bestc;
                E.s++;
                pq.push(E);
            }
            else
                delete []E.x;                               //舍弃扩展结点
        }
        else                                                //产生当前扩展结点儿子结点
        {
            for(i = E.s+1; i < n; i++)
                if(a[E.x[E.s]][E.x[i]] != NoEdge)
                {
                    //可行儿子结点
                    cc = E.cc + a[E.x[E.s]][E.x[i]];        //当前费用
                    rcost = E.rcost - MinOut[E.x[E.s]];     //更新最小出边费用和
                    b = cc + rcost;                         //下界
                    if(b < bestc || bestc == NoEdge)        //子树可能含最优解 结点插入最小堆
                    {
                        N.s = E.s + 1;
                        N.cc = cc;
                        N.lcost = b;
                        N.rcost = rcost;
                        N.x = new int[n];
                        for(j = 0; j < n; j++)
                            N.x[j] = E.x[j];
                        N.x[E.s+1] = E.x[i];                //获得新的路径
                        N.x[i] = E.x[E.s+1];
                        pq.push(N);                         //加入优先队列
                    }
                }
 
            delete []E.x;                                   //完成结点扩展
        }
        if(pq.empty())                                      //堆已空
            break;
        E = pq.top();                                       //取下一扩展结点
        pq.pop();
    }
 
    if(bestc == NoEdge)                                     //无回路
        return NoEdge;
    for(i = 0; i < n; i++)                                  //将最优解复制到v[1:n]
        v[i+1] = E.x[i];
    while(pq.size())                                        //释放最小堆中所有结点
    {
        E = pq.top();
        pq.pop();
        delete []E.x;
    }
 
    return bestc;
}

到了这里,关于NJUPT算法分析与设计期末考试202.12.1的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

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

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

    2024年02月04日
    浏览(43)
  • 算法设计与分析期末复习题

    1.应用Johnson法则的流水作业调度采用的算法是(D) A. 贪心算法 B. 分支限界法 C.分治法 D. 动态规划算法 2.Hanoi塔问题如下图所示。现要求将塔座A上的的所有圆盘移到塔座B上,并仍按同样顺序叠置。移动圆盘时遵守Hanoi塔问题的移动规则。由此设计出解Hanoi塔问题的递归算法正

    2024年02月09日
    浏览(38)
  • 算法设计与分析-期末复习经典例题

    算法设计应满足的目标:正确性,可使用,可读,健壮,高效率,低存储 算法的5个重要特征:有限、确定、可行、输入、输出 通常用 函数的返回值 表示算法能否正确执行,如果某个形参需要将执行结果回传给实参,需要将该形参设计为 引用型参数 算法分析是分析算法 占

    2024年02月03日
    浏览(50)
  • 【期末复习】计算机算法设计与分析

    小编相信大家都很急切,要如何短时间学会算法通过考试呢?下面就让楼主带大家一起了解吧。 算法期末考试,其实就是算法期末考试了。那么小编为什么会算法期末考试,相信大家都很好奇是怎么回事。大家可能会感到很惊讶,小编怎么会算法期末考试呢?但事实就是这样

    2024年02月03日
    浏览(42)
  • 计算机算法设计与分析期末复习

    以下是我的部分算法笔记,希望可以给复习的小伙伴们参考一下: 题目: 一切合法的输入数据都能得出满足要求的结果,包括典型的、苛刻的输入数据也能够得出满足要求的结果。这个含义对应算法的(正确性) 算法要对异常情况进行适当的处理,就是算法的(健壮性)

    2024年02月13日
    浏览(41)
  • 算法设计与分析 期末复习 北邮BUPT

    以下内容以“算法设计与分析-2022”王晓茹老师的ppt为大纲 问题、要求 也均为老师课堂上的口述要求和ppt上的要求 渐进上界、渐进下界 证明 O ( f ( n ) ) + O ( g ( n ) ) = O ( m a x { f ( n ) , g ( n ) } ) O(f(n))+O(g(n)) = O(max{f(n),g(n)}) O ( f ( n )) + O ( g ( n )) = O ( ma x { f ( n ) , g ( n )}) (最后一

    2024年01月16日
    浏览(55)
  • 算法设计与分析期末复习题(史上最详细)

    算法设计与分析期末复习题(一) 1、二分搜索算法是利用( A )实现的算法。 A、分治策略 B、动态规划法 C、贪心法 D、回溯法 2、下列不是动态规划算法基本步骤的是( A )。 A、找出最优解的性质 B、构造最优解 C、算出最优解 D、定义最优解 3、最大效益优先是( A )的一

    2023年04月09日
    浏览(50)
  • 《NJUPT》网络信息安全_期末PPT整理笔记

    信息安全包括:信息安全管理、物理场所安全、设备的硬件安全、软件安全(操作系统/其他系统软件应用软件)、网络信息安全(TCP/IP )、密码学的应用、信息隐藏、其他不常见技术 不同的研究方向: 1)攻击技术:身份隐藏、踩点、扫描、查点、嗅探、拒绝服务攻击、口

    2024年02月09日
    浏览(42)
  • 天津理工大学研究生学位课《算法设计与分析》期末大作业

    2022级电子信息天理研究生 答: 属于T(n)=aT(n/b)+cn k的形式,其中cn k表示问题分解成子问题和将子问题的解合并成原问题的解的时间。 此时a=9,b=3,k=1,cn k=n。所以f(n)=Θ(n logb a)=Ω(n)=O(n 2) 答: 对于T1来说它表示随着问题规模n的增大,算法的执行时间的增长率与f(n)的增长率相同

    2024年01月19日
    浏览(45)
  • C++程序设计期末考试复习试题及解析 3(自用~)

    可以很清楚看到浅拷贝所造成的错误:在析构的时候会重复析构,这是由于浅拷贝时,b的buffer指针和a的buffer指针指向的是同一片空间 如何更改? 换为深拷贝! 即弃用默认拷贝构造函数,自己写一个拷贝构造函数 改为深拷贝后,a、b对象不会相互影响,由于b未调用set()函

    2024年02月09日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包