首页 > 编程语言 >【算法与设计】期末总结

【算法与设计】期末总结

时间:2024-06-20 12:31:31浏览次数:14  
标签:总结 int 矩阵 问题 算法 期末 最优 贪心

文章目录

  • 第一章 概述
    • 算法与程序
    • 时间复杂性
    • 求上界
  • 第二章 递归与分治
    • 双递归函数——Ackerman函数
    • 分治策略
      • 大整数乘法
        • 两位×两位
        • 四位x四位
      • 三位x三位
        • 两位x六位
  • 第三章 动态规划
    • 矩阵连乘
    • 基本要素
      • 最优子结构
      • 子问题重叠
    • 备忘录
  • 第四章 贪心算法
    • 活动安排问题
    • 基本要素
      • 贪心选择性质
      • 最优子结构性质
      • 与动态规划的区别
    • 背包问题
      • 物体可分
      • 物体不可分
  • 第五章 回溯法
    • **问题的解空间**
    • 0-1背包
    • 迭代回溯
    • 0-1背包问题(树结构)
  • 期末考点

第一章 概述

算法与程序

算法:解决问题的一种方式或者一种过程。算法有若干个指令组成的有穷序列。
程序:算法用某种程序设计语言的具体实现

算法的4种性质:

  • 输入
  • 输出
  • 确定性
  • 有限性

程序可以不满足“有限性”

时间复杂性

算法复杂度的高低体现在运行该算法所需要的计算机资源的多少上。资源的多少依赖于要解决问题的规模(N)、算法的输入(I)和算法本身的函数(A)

关于时间复杂性,分为三种情况:最坏情况、最好情况和平均情况。
可操作性最好且最有实际价值的是最坏情况的时间复杂度

求上界

当N>=N0时有f(N)<=Cg(N),称为函数f(N)的一个上界是Cg(N),记作f(N)=O(g(N))
这个上界的阶越低,则评估越精确,结果越有价值

如何求上界?
1.把f(N)函数中的所有阶放大到最高阶,合并后并记为Cg(N)
2.此时f(N)<=Cg(N),把这两个函数去化简即可得条件,即n值。

例子:f(n)=3n2+10n
最高阶是n2,所有阶放大到最高阶得3n2+10n2=13n2,记为Cg(N)
此时,C=13,g(N)=n2
当3n2+10n <= 3n2+10n2时,即10n <= 10n2时,条件成立。
故n0>=1
综上,当n0=1时,C=13,f(n)=O(n2)

注意:放大方向不变,方式可以改变(即可以增大阶层且缩小系数),如3n2+10n <= 3n2+n2,此时结果的C和n0都不一样,但f(n)始终一样。

第二章 递归与分治

递归:代码效率好,但是空间效率和时间效率差

如何改进??
消除递归,有两种方式:阶乘(循环)和阶加(循环、通项公式)

双递归函数——Ackerman函数

定义:一个函数及它的一个变量由函数自身定义时

分治策略

基本思想:将问题分解为k个小规模的子问题,这些子问题相互独立且原问题相同。递归地解这些子问题,将个子问题的解合并得到原问题的解。

大整数乘法

普通乘法的时间复杂度是O(n2)
通过分支策略可达到O(n1.59)

两位×两位

步骤:
1.两位数分出高低位
2.套用公式求p,q,r

遇到负数,高低位都带符号
如-23:高位-2,低位-2。至此,-23=(-2)*10+(-3)

最简的分治(递归出口):一位x一位

四位x四位

一直递归,直到满足出口

三位x三位

往前补0,公式不变

两位x六位

补零或者把六位拆成3个两位

第三章 动态规划

动态规划分治
分解子问题分解子问题
子问题相互依赖子问题相互独立

基本思想:
分解成子问题求解时,有些子问题被重复计算许多次。用一个记录所有已解决的子问题的答案,而在需要时再找出已求得的答案,就可以避免大量的重复计算。

步骤:
1.找到最优解,刻画其结构性质
2.递归地定义最优值
3.以自底向上的方式计算最优值
4.根据计算最优值时得到的信息,构造最优解

矩阵连乘

题目背景:
若两矩阵相乘,需满足第一矩阵的行=第二矩阵的列
即Amxn X Bpxq的条件为n==p
此时,乘法次数为=m x n x q

连乘次序会影响乘法次数

按照上述步骤:
1.最优解及其结构性质:最小乘法次数 及 最小乘法次数的断开处
记A[i:j]是AiAi+1…Aj
问题:A[1:n],可以在k=1,2,⋯n−1处断开,若A[1:n]最优,则A[1:k]与A[k+1:n]也最优

2.建立递归关系
记A[i:j],其中1≤i≤j≤n,最少乘法次数记m[i][j]
(1)当i=j时→ A[i:i] →指A[i] 本身→乘法次数为0,即 m[i][j]=0
(2)当i<j时, 在k处断开, k可以取值i, i+1, ∙∙∙, j−1,在某k处乘法次数最少

在这里插入图片描述
定义数组p存储矩阵信息
p[0]为第1矩阵的行
p[1]为第1矩阵列(也为第2矩阵行)
p[2]为第2矩阵列(也为第3矩阵行)
p[3]为第3矩阵列(也为第4矩阵行)

p[n]为第n矩阵列

3.计算最优值
对于结果的存储,使用m表存储最小乘法次数(即最优值),用s表存储k值(即最优解)

代码实现:

//构造最优值
void MatrixChain(int *p, int n, int **m, int **s)//P一维数组记下标;n矩阵个数;m表;s记分段
{
	for(int i=1;i<=n;i++)
		m[i][i]=0;//对角线上都填0

	for(int r=2;r<=n;r++)//在m表中,从第2条填到第n条(对角线)
		for(int i=1;i<=n-r+1;i++)//i是行下标,从第1行开始填一个倒三角的表
		{
			int j=i+r-1;//列下标
			m[i][j]=0+m[i+1][j]+p[i-1]*p[i]*p[j];//实现递归计算,先初始化第1项,省略了m[i][i]
			s[i][j]=i;//s记分段点,此为s的初值

			for(int k=i+1;k<j;k++)//递归式从k=i+1到j-1,找最小
			{
				int t=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];//递归式计算 
                if(t<m[i][j])
				{
					m[i][j]=t;//记入最小值
					s[i][j]=k;//记入划分位置
				}
			}
		}
}

4.构造最优解
算法MatrixChain只是计算出了最优值,并未给出最优解。但是MatrixChain已记录了构造最优解所需要的全部信息。s[i][j]中的数表明,最佳方式应在矩阵的何处断开。

//构造最优解
void Traceback(int i,int j,int **s)//求A[i:j]的最优解构造,利用s[][],设已知s[i][j]=k
{
	if(i==j)
		return ;//A[i:i]不必构造,递归出口

	Traceback(i,s[i][j],s);//求A[i:k]的构造,记1
    Traceback(s[i][j]+1,j,s);//求A[k+1:j]的构造,记2
	cout<<"Multiply A["<<i<<":"<<s[i][j]
		<<"]and A["<<(s[i][j]+1)<<":"<<j<<"]"<<endl;//输出Ai,k And Ak+1,j,表明在k处断开,记3
}

基本要素

最优子结构

设计动态规划算法的第一步通常是要刻画最优解的结构。
当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。

子问题重叠

在用递归算法自顶向下解此问题时,每次产生的子问题并不总是新问题,有些子问题被反复计算多次。
动态规划算法正是利用了这种子问题的重叠性质,对每一个子问题只解一次,而后将其解保存在一个表格中,当再次需要解此子问题时,只是简单地用常数时间查看一下结果。

备忘录

动态规划的变形——备忘录

动态规划:保存所有子问题的解
变形:动态规划是自底向上;备忘录是自顶向下

第四章 贪心算法

工作量:贪心算法 < 动态规划
但是贪心算法的结果可能不是最优结果,因为贪心算法并不是从整体最优上加以考虑,它所做出的选择只是某种意义上的局部最优选择

所以,贪心算法的关键是贪心策略的选择

活动安排问题

该问题要求高效地安排一系列争用某一个公共资源的活动。有n个活动,开始和结束的时间si≤fi,如何安排最多个活动?

贪心策略:按结束时间递增排序,从前向后能安排则安排

例题:当前有4个活动。

i1234
s[i]1305
f[i]4567

若选择最早结束优先,能使选入活动最多
若最早开始优先,仅能安排这一个活动
若最短占用优先,则能安排这一个活动

推广:
假设要在足够多的的会场里安排一批活动,即每个活动都要被安排,并希望使用尽可能少的会场。
(1)贪心策略思路1:先在第1会场安排最多活动,其次在第2会场安排最多,……,依此类推 。
(2)贪心策略思路2:视为区间重叠问题。时间点:起点和终点。
按时间点排序起点分配1个会场,终点回收,保证此会场可重复利用
在这里插入图片描述
在这里插入图片描述

基本要素

贪心选择性质

贪心选择性质是指所求问题的整体最优解是可以通过局部最优的选择,即贪心选择达到的。
动态规划算法中,每步所做的选择往往依赖于相关子问题的解。因而只有在解出相关子问题后,才能做出选择。
而在贪心算法中,仅在当前状态下做出最好选择,即局部最优选择。然后再去解做出这个选择后产生的相应子问题。

最优子结构性质

最优子结构性质是该问题可用动态规划算法或贪心算法求解的关键特征。

与动态规划的区别

**贪心算法:**先依据贪心策略选择并解一个子问题,再进行下一步。
**动态规划算法:**先解决所有的子问题,比较得出一个最优子问题,再进行下一步。

背包问题

问题描述:容量为c的背包,有n种物品,每种物品重w_i,价值为v_i,其中1≤i≤n,
物品不可(可以)分开。
问:如何装入使价值最大?

cnw1w2w3v1v2v3
50310203060100120

物体可分

c>0,wi>0,vi>0,1≤i≤n。找(x1,x2,⋯,xn),0≤xi≤1,可为分数,即仅取一部分,
使 ∑ i = 1 n w i ∗ x i < = c \sum_{i=1}^{n} wi*xi<= c i=1∑n​wi∗xi<=c 达到最大
∑ i = 1 n v i ∗ x i \sum_{i=1}^{n} vi*xi i=1∑n​vi∗xi

//物品可分:贪心算法 
#include <iostream>
#include <iomanip> 
using namespace std;

void Knapsack(int n, int c, int*v, int *w, double *x);

int main() 
{	
	int n=3;//物品数量 
	int c=50;//背包容量 
	int *v=new int[n+1];//价值 
	int *w=new int[n+1];//重量 
	int i;
	double *x=new double[n+1];	
	for(i=1;i<=n;i++)
		x[i]=0;	
	
	//将数据按贪心策略排序 
	v[1]=60;v[2]=100;v[3]=120;
	w[1]=10;w[2]=20;w[3]=30;
	
	Knapsack(n,c,v,w,x); 
	
	for(i=1;i<=n;i++)
	{		
		if(x[i]>0)
			cout<<"物品"<<i<<"装入"<<setiosflags(ios::fixed)<<setprecision(2)<<x[i]<<endl;
		else
			cout<<"物品"<<i<<"不装入"<<endl;
	}
		
	return 0;
}

void Knapsack(int n, int c, int*v, int *w, double *x)
{
	int i;
	
	for(i=1;i<=n;i++)
	{
		if(w[i]>c)
			break;
		else
		{
			x[i]=1;
			c=c-w[i]; 
		}			
	}	
	if(i<=n)	
		x[i]=(double)c/w[i];		
}

step1:准备
按单位价格递减排序,x[ ]初值为0,先都没选
step2:循环
按递减装入物品至不可装为止,从1检查到n
物品装入置x[i]=1,c=c−w[i]
step3:最后
将当前i物品分开,送入c/w[i]

物体不可分

其中,c>0,wi>0,vi>0,1≤i≤n,
找(x1,x2,⋯,xn),xi∈{0,1},
(物品没装xi=0,装入xi=1)
使 ∑ i = 1 n w i ∗ x i < = c \sum_{i=1}^{n} wi*xi<= c i=1∑n​wi∗xi<=c 达到最大
∑ i = 1 n v i ∗ x i \sum_{i=1}^{n} vi*xi i=1∑n​vi∗xi

根据上述步骤:
1.最优子结构性质
若(y_1,y_2,⋯,y_n)是最优解,则(y_2,⋯,y_n)是子问题的最优解

2.递归关系
m(i,j)记背包容量j,可选物品为i,i+1,⋯,n时,0-1背包问题的最优解
在这里插入图片描述
3.计算最优值

template <class Type>
void Knapsack(Type *v, int *w, int n, Type **m)
{
	int jMax=min(w[n]-1,c);//找<w[n]的临界值,并避免物品n比背包容量还要大的情况 
	
	//最小子问题,填写最后一行m[n][j] 
	for(int j=0;j<=jMax;j++)
		m[n][j]=0;
	for(int j=w[n];j<=c;j++)
		m[n][j]=v[n];
		
	 
	for(int i=n-1;i>1;i--)
	{
		jMax=min(w[i]-1,c);
		for(int j=0;j<=jMax;j++)
			m[i][j]=m[i+1][j];//物品i装不进去
		for(int j=w[i];j<=c;j++)
			m[i][j]=max(m[i+1][j],m[i+1][j-w[i]]+v[i]);//能装但不装,装进去,两个值中取较大值 
	}
	
	//填最后一行 
	m[1][c]=m[2][c];//若物品1装不进去 
	if(c>=w[1])//若物品1可以装 
		m[1][c]=max(m[2][c],m[2][c-w[1]]+v[1]); 
}
 step1:实现递归出口,填矩阵m的第n行(前3行)
 step2:循环,实现递归式,填矩阵m的第(n−1)行到第2行
 step3:填m[1][c]

4.构造最优解

template <class Type>
void Traceback(Type **m, int *w, int c, int n, int *x)//m表已经填好,已知w、c、n,输出x[],0不装,1装入
{
	for(int i=1;i<n;i++)
	{
		if(m[i][c]==m[i+1][c])
			x[i]=0;//相同则不装
		else
		{
			x[i]=1;
			c-=w[i];
		}
	}

	x[n]=(m[n][c])?1:0;		

}

第五章 回溯法

溯法有“通用的解题法”之称。
用它可以系统地搜索一个问题的所有解或任意解
它在问题的解空间树中,按深度优先策略,从根结点出发搜索解空间树。算法搜索至解空间树的任一结点时,先判断该结点是否包含问题的解。如果肯定不包含,则跳过对以该点为根的子树的搜索,逐层向其祖先结点回溯;否则进入该子树,继续按深度优先策略搜索。

问题的解空间

 用回溯法解问题时,应明确定义问题的解空间。
指包含解的“集合”,结构常为树或者图。
问题的解空间至少应包含问题的一个(最优)解。

0-1背包

迭代回溯

有两种方案:
第一种是保存所有子集
第二种是添加剪枝函数

3个状态:左子树、右子树、回溯
在左、右子树添加约束函数、限界函数

两种剪枝函数:
约束函数:在扩展结点处剪去不满足约束的子树;
限界函数:剪去得不到最优解的子树。

0-1背包问题(树结构)

期末考点

1.熟练求出上界的n0,C,g(N)
2.清楚Ackerman函数的代码实现
3.熟练掌握大整数相乘的p,q,r;掌握其求解过程
4.清楚大整数乘法的代码实现,尤其是递归出口
5.掌握动态规划中0-1背包的代码实现、m表、s表、及其求最优值的解
6.在动态规划中0-1背包的代码中,可能会考察代码填空,变量的各阶段的值
7.掌握备忘录代码的具体实现
8.回溯法中的旅行售货员内容 及 整本书的定义内容不会考察。

掌握的意思是必考清楚代表可能重点考察

期末在头歌上考,有代码填空及代码分析两种题型

标签:总结,int,矩阵,问题,算法,期末,最优,贪心
From: https://blog.csdn.net/2201_75475240/article/details/139639251

相关文章

  • HTTP详细总结
    概念HyperTextTransferProtocol,超文本传输协议,规定了浏览器和服务器之间数据传输的规则。特点基于TCP协议:面向连接,安全TCP是一种面向连接的(建立连接之前是需要经过三次握手)、可靠的、基于字节流的传输层通信协议,在数据传输方面更安全。基于请求-响应模型的:一次请......
  • 项目总结
    项目总结:关爱老人项目引言本文档旨在总结关爱老人项目的开发过程和取得的成果。项目从需求分析、设计到实现,以及后续的测试和发布,全面回顾并分析了项目中的关键步骤和决策过程。总体设计项目采用了B/S架构,主要涉及运动打卡和点菜系统两大功能模块。运动打卡系统实现了计时......
  • JavaScript基础部分知识点总结(Part3)
    函数的概念1.函数的概念在JS里面,可能会定义非常多的相同代码或者功能相似的代码,这些代码可能需要大量重复使用。虽然for循环语句也能实现一些简单的重复操作,但是比较具有局限性,此时我们就可以使用JS中的函数。函数:就是封装了一段可被重复调用执行的代码块。通过此代码块可......
  • Windows安全加固总结(非常详细)零基础入门到精通,收藏这一篇就够了
    为了达到安全的目的,一般来说我们需要关注操作系统的八个方面:补丁管理>账号漏洞>授权管理>服务管理>功能优化>文件管理>远程访问控制>日志审计其中:补丁管理使用最新版的补丁,避免使系统存在已知的漏洞,从而被攻击者利用。账号口令梳理出系统中正在使......
  • 基于稀疏矩阵方法的剪枝压缩模型方案总结
    1.简介1.1目的在过去的一段时间里,对基于剪枝的模型压缩的算法进行了一系列的实现和实验,特别有引入的稀疏矩阵的方法实现了对模型大小的压缩,以及在部分环节中实现了模型前向算法的加速效果,但是总体上模型加速效果不理想。所以本文档针对这些实验结果进行分析和总结。1.2范围......
  • Beta版总结会议
    项目总结项目名称:冀网社区聘项目概述:本项目旨在开发一个校园兼职招聘系统,为学生提供便捷的兼职发布、搜索功能,以及社交交流和广告展示等服务。项目由李健龙领导,郑盾作为核心开发人员之一,团队努力推动各项功能的设计、开发和上线工作。项目成果与问题:在项目开发的过程中,团队取......
  • 电路分析期末总结笔记上
    电流,电压定义及单位电流(Current)的定义是单位时间内通过导体横截面的电荷量。电压(Voltage),又称作电势差或电位差,是衡量单位电荷在静电场中由于电势不同而产生的能量差的物理量。 参考方向,关联参考概念U,I采用相同的参考方向,为正U,I采用不相同的参考方向,为负功率的计算......
  • 算法金 | 再见!!!梯度下降(多图)
    大侠幸会,在下全网同名「算法金」0基础转AI上岸,多个算法赛Top「日更万日,让更多人享受智能乐趣」接前天李沐:用随机梯度下降来优化人生!今天把达叔6脉神剑给佩奇了,上吴恩达:机器学习的六个核心算法!——梯度下降1、目标梯度下降优化算法的概述,目的在于帮助读者......
  • C语言期末复习笔记
    目录一,基础介绍。二,标识符起名规范。三,数据类型。四,变量。五,运算符和表达式1,加减乘除​编辑  /为整除,%为余数,*为乘号2,关系运算符3,逻辑运算符4,运算符优先级5,前自增,后自增6,三目运算符。7,符合运算符。六,控制语句。1,if判断2,多重判断。3,for循环4,while循环5,d......
  • 基于变异混合蛙跳算法的车间调度最优化matlab仿真,可以任意调整工件数和机器数,输出甘
    1.程序功能描述变异混合蛙跳算法的车间调度最优化,可以任意调整工件数和机器数,输出甘特图。 2.测试软件版本以及运行结果展示MATLAB2022a版本运行                     3.核心程序%初始种群Pop_n=round(sqrt(Npop));......