计算机算法设计与分析第三章思维导图及知识点总结

思维导图

详细内容、问题介绍、最优子结构证明、状态转移方程以及物理意义、部分代码均在下文展示。

动态规划算法的概念

        动态规划时运筹学的一个分支,时求解解决决策过程最优化的过程。

        动态规划算法与分治法类似,其基本思想是将待求解问题分解成若干个子问题,先求解子问题,在结合这些子问题的解得到原问题的解。与分治法不同的是,适合用动态规划发求解的问题经过分解得到的子问题往往不是相互独立的。

一、动态规划算法的基本要素

1.最优子结构

        设计动态规划算法的第一步通常是要刻画最优解的结构。当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质。在动态规划算法中,利用问题的最优子结构性质,以自底向上的方式递归地从子问题地最优解逐步构造出整个问题的最优解。

        最优子结构的作用用于确保算法的正确性。

2.重叠子问题

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

        重叠子问题的作用为提高算法的时间效率。

3.备忘录方法

        备忘录方法是动态规划算法的变形。备忘录方法用表格保存已解决的子问题的答案,下次需要解此问题时,只需要查看此子问题的解。但与动态规划不同的是,备忘录方法的递归方式是自顶向下的。

二、设计动态规划算法的步骤

1.找出最优解的性质,并刻画其结构特征

2.递归的定义最优值

3.以自底向上的方式计算最优质

4.根据计算最优值时得到的信息构造最优解

三、矩阵连乘问题

问题描述:对于给定的相继n个矩阵{A1,A2,```,An}(矩阵Ai的维数为pi-1*pi,i=1,2,```,n),如何确定计算矩阵连乘积A1A2,```An的计算次序(完全加括号方式),使得依次次序计算矩阵连乘需要的数乘次数最少。

求解问题步骤:

1.分析最优解的结构

        计算A[1:n]的最有次序所包含的计算矩阵子链A[1:k]和A[k+1:n]的次序也是最优的。

        如果计算A[1:k]的次序需要的计算量更少,则用此次序替换原来计算A[1:k]的次序,得到的计算A[1:n]的计算量将比最有次序所需计算量更少,这是一个矛盾,同理可证A[k+!:n]的次序也是最优的,则由此证明最有子结构。

2.建立递归关系

状态转移方程

        m[i][j]\left\{\begin{matrix} 0 & i=j\\ min(i<=k<j)(m[i][k]+m[k+1][j]+pi-1*pk*pj) & i<j \end{matrix}\right.

物理意义:m[i][j]表示计算矩阵A[1:n]所需的最小数乘次数。

3.计算最优值      

void MatrixChain(int *p,int n,int **m,int **s){
    for(int i=1;i<=n;i++)
        m[i][i]=0;
    for(int r=2;r<=n;r++){
        for(int i=1;i<=n-r+1;i++){
            int j=i+r-1;
            m[i][j]=m[i+1][j]+p[i-1]*p[i]p[j];
            s[i][j]=i;
            for(int k=i+1;k<j;k++){
                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.构造最优解

void TraceBack(int i,int j,int **s){
    if(i==j)
	{
		cout << "A" << i;
		return ;
	}
	cout << "(";
	TraceBack(i,s[i][j]);
	TraceBack(s[i][j]+1,j);
	cout << ")";
}

四、最长公共子序列

问题描述:给定两个序列X和Y,当另一个序列Z既是X的子序列又是Y的子序列,称Z是序列X和Y的公共子序列。

求解问题步骤:

1.分析最优子结构

        最长公共子序列具有最优子结构性质。设序列X={x1,x2,```,xm}和Y={y1,y2,```yn}的最长公共子序列为Z={z1,z2,```,zk},则有

        ①若xm=ym,则zk=xm=yn,且Zk-1是Xm-1和Yn-1的最长公共子序列。

        ②若xm!=yn且zk!=xm,则Z是Xm-1和Y的最长公共子序列。

        ③若xm!=yn且zk!=yn,则Z是Xm-1和Y的最长公共子序列。

证明:反证法

        若zk!=xm,则{z1,z2,```,zk, xm}是X和Y的长度为k+1的公共子序列。这与Z是X和Y的最长公共子序列矛盾,因此必有zk=xm=yn。由此可知,Zk-1是Xm-1和Y的长度为k-1的公共子序列。若Xm-1和Yn-1有长度大于k-1的公共子序列W,则将xm加在其尾部产生X和Y的长度大于k的公共子序列。此为矛盾。

2.子问题的递归结构

状态转移方程

c[i][j]\left\{\begin{matrix} 0 & i>0;j=0\\ c[i-1][j-1]+1 & i,j>0;xi=yi\\ max(c[i][j-1],c[i-1][j]) & i,j>0;xi!=yi \end{matrix}\right.

物理意义:m[i][j]表示序列X前i位和序列Y前j位的最长公共子序列。

3.计算最优值

void lcs(string s1,string s2)
{
	for(int i=0;i<=s1.length();i++)
		m[i][0]=0;
	for(int j=0;j<=s2.length();j++)
		m[0][j]=0;
	for(int i=1;i<=s1.length();i++)
	{
		for(int j=1;j<=s2.length();j++)
		{
			if(s1[i]==s2[j])
			{
				m[i][j]=m[i-1][j-1]+1;
				b[i][j]=3;
			}
			else{
				if(m[i][j-1]>m[i-1][j])
				{
					m[i][j]=m[i][j-1];
					b[i][j]=2;
				}
				else {
					m[i][j]=m[i-1][j];
					b[i][j]=1;
				}
			}
		}
	}
	cout << m[s1.length()][s2.length()]<<endl;
}

4.构造最优解

void TraceBack(string s1,string s2)
{
	int i=s1.length();
	int j=s2.length();
	int n=0;
	while(i!=0&&j!=0)
	{
		if(b[i][j]==3)
		{
			t[n++]=s1[i-1];
			i--;j--;
			
		}
		else if(b[i][j]==2)
		{
			j--;
		}
		else i--;
	}
}

五、0-1背包问题

问题描述:给定n种物品和一背包。物品i的重量是wi,其价值vi,背包的容量为c,问应如何选择装入背宝中的物品,使得装入背宝中物品的总价值最大?

1.最优子结构性质

 证明:设(y1,y2,```,yn)是所给0-1背包问题的一个最优解,则(y2,```,yn)是下面相应子问题的一个最优解。如果设(z2,z3,```,zn)是上述子问题的一个最优解,而(y2,```,yn)不是它的最优解,而说明(z1,z2,z3,```,zn)是所给0-1背包问题的一个更优解,次为矛盾。

2.递归关系

状态转移方程

m[i][j]\left\{\begin{matrix} m[i-1][j] & 0<=j<wi\\ max(m[i-1][j],m[i-1][j-wi]+vi) &j>wi \end{matrix}\right.

物理意义:

m[i][j]表示为前i件物品放入重量为j的背包中的最大价值。

3.计算最优值

void solve(int n,int W)
{
	for(int i=0;i<=W;i++)
		m[0][i]=0;
	for(int i=0;i<=n;i++)
		m[i][0]=0;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=W;j++)
		{
			if(w[i]>j)
				m[i][j]=m[i-1][j];
			else{
				m[i][j]=max(m[i-1][j],m[i-1][j-w[i]]+v[i]);
			}
		}
	}
}

4.构造最优解

void TraceBack(int n,int W)
{
	int i=n;
	int j=W;
	while(i!=0&&j!=0)
	{
		if(m[i][j]==m[i-1][j])
		{
			s[i]=0;
			i--;
		}
		else{
			j=j-w[i];
			s[i]=1;
			i--;
		}
	}
}

六、最优二叉搜索树

问题描述:对于有序集S及其存取概率分布(a0,b1,a1,```,bn,an),在所有表示有序集S的二叉搜索树中找出一棵具有最小平均路长的二叉搜索树。

1.最优子结构性质

证明:Tl是关于集合(xi,````,xm-1)的一棵二叉搜索树,则pl>=pi,m-1。若pl>pi,m-1,则用Ti,m-1替换Tl可得到平均路长比Tij更小的二叉搜索树,这与Tij是最优二叉搜索树矛盾,则Tl是一棵最优二叉搜索树。

2.建立递归关系

w[i][j]\left\{\begin{matrix} qi-1 & j=i-1\\ w[i][j-1]+pj+qj& i<=j \end{matrix}\right.

e[i][j]\left\{\begin{matrix} qi-1 & j=i-1\\ min(e[i][r-1]+e[r+1][j]+w[i][j])i<=r<=j & i<=j \end{matrix}\right.

物理意义

w[i][j]表示从节点i到节点j的概率和

e[i][j]表示节点i到节点j以r为根节点的最优二叉树

七、图像压缩

问题描述:要求确定像素序列{p1,p2,```,pn}的一个最有分段,使得依次分段所需的存取空间最小。

1.最优子结构性质

        设l[i]和b[i](l<=i<=m)是{p1,p2,```,pn}的一个最优分段。显然l[1]和b[1](l<=i<=m)是{p1,p2,```,pn}的一个最优分段明,且l[i]和b[i](2<=i<=m)是{pl[1]+1,p2,```,pn}的一个最优分段,即图像压缩问题满足最优子结构性质。

2.建议递归关系

s[i]=min(l<=k<=min{i,256}){s[i-k]+k*bmax(i-k+1,i)}+11;其中bmax(i,j)=log(max(i<=k<=j){pk}+1).

物理意义:s[i]表示是像素序列{p1,p2,```,pn}的最有分段所需的存储位数。

八、最大子段和

问题描述:给定由n个整数(可能是负整数)组成的序列a1,a2,```,an,求该序列形如\sum ak的字段和的最大值。

状态转移方程:

dp[ j ] = max (dp[j−1]+a [j],a[j])(1<=j<=n)

物理意义:

dp[j]表示前j个数中最大的连续字段和

九、凸多边形最优三角剖分

问题描述:给定凸多边形P={v0,v1,```,vn-1},以及定义在凸多边形的边和弦组成的三角形上的权函数w,要求确定该凸多边形的三角剖分,使得该三角剖分所对应的权,即三角剖分中诸三角形上权之和是最小。

状态转移方程

m[i][j]\left\{\begin{matrix} 0 & i=j\\ min i<=k<=j(m[i][k]+m[k+1][j]+w(vi-1vjvk)&i<j \end{matrix}\right.

物理意义:

m[i][j](1<=i<j<=n)为凸子多边形 (vi−1,vi,```, vj)的最优三角剖分对应的最优值

十、多边形游戏

问题描述:对于给定的多边形,计算最高得分。游戏的得分就是所剩定点上的整数值

递归求解:

(1) 当op[i+s]=’+’时

   m[i,j,0]=a+c ;m[i,j,1]=b+d

(2) 当op[i+s]=’*’时

  m[i,j,0]=min{ac,ad,bc,bd} 

  m[i,j,1]=max{ac,ad,bc,bd}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值