算法设计与分析第三章作业

5325465 2022级 2023-10-22 18:27:24

第三章:动态规划

使用动态规划技术的问题特征

■最优子结构性质当一个问题的最优解包含了其子问题的最优解时,我们说这个问题具有最优子结构。重叠子问题性质在问题的求解过程中,很多子问题的解会被多次使用。

(1.  动态规划法是将待求解问题分解成若干子问题,先求解子问题再结合这些子问题的解得到原问题的解。但动态规划法里的子问题和分治法里的子问题不同,动态规划法中的子问题并不是相互独立的,所以会存在重复计算子问题的情况。

(2.  使用动态规划算法的问题有两个特征:1.有最优子结构性质(子问题的最优解合成原问题的最优解)  2.有重复子问题性质

(3.  动态规划算法采用自底向上的填表法,该法要考虑三个问题:1.表的维数  2.填表的范围  3.按什么顺序填

       (另有自上而下的备忘录方法)

  (4.  使用动态规划算法时:1.找到最优子结构  2.写出状态表示和状态方程,以及边界条件   3.根据状态方程决定表的维数、范围、填表顺序。  4.填表,先注意边界条件

 

矩阵联乘问题

/*
	思路:这里在考虑的的时候,因为是多个矩阵相乘,求的最小乘法次数,
		  比如 A1*A2*A3*A4, 那么根据划分的不同,那么其乘法顺序也会不同,继而所求的乘法次数也不一样
		 划分:((A1*A2)*A3) *A4 等等,那么再求解最小乘法次数的时候,这就涉及到是个
		 动态的过程 
		 在用 动态划分的思想做的时候,先创建一个二维数组,用来存放不同个数矩阵相乘的
		 最小乘法次数,然后根据划分 来求得最小的乘法次数 
  */

#include<bits/stdc++.h>
using namespace std;

int N;
int p[1000];
int m[1000][1000];  //m[i][j] 即表示:A(i)A(i+1)(i+2)...A(j); 

int minimum_num(){
	//初始化矩阵,一个矩阵乘法次数为0 
	for(int i = 1; i <= N; i++)
	m[i][i] = 0;
	
	//向二维数组中添加数据,并更新(求最小),
	
	for(int i = N; i >= 1; i--){//这里的i 从 N 先开始,不能从1 先开始,因为一旦从1开始  
							    //那么的话 m[1][N],就在第一次循环便求出,那么m[1][N]在划分 
							    //更新的时候,其中的一些值尚未求出来。如果从N开始,那么最后求得是
								//m[1][N],这样就可以用到了前面已经求出的一些值
		for(int j = i + 1; j <= N; j++){
			//任何一个m[i][j],均可这样先表示出来 即从 i 后面开始划分 
			m[i][j] = m[i][i] + m[i+1][j] + p[i-1]*p[i]*p[j]; 
			
			//划分更新
			for(int k = i + 1;k < j; k++){//这里 k = i + 1 ,表示的是从i+1后面开始划分,
										 //因为上方第一次表示出来的时候,就已经是从 i 后面划分了  
				int temp = m[i][k] + m[k+1][j] + p[i-1] * p[k] * p[j];
				
				if(temp < m[i][j]){
					m[i][j] = temp;
				}
					
			} 		
		}							 
		
	} 
	
	return m[1][N];

}


int main(){
	
	cin >> N;
	
	for(int i = 0; i < N + 1; i++){
		cin >> p[i];
	}
	
	int result = minimum_num();
	
	cout << result;
	
} 

 或者

#include <bits/stdc++.h>

using namespace std;

const int MAX = 1005;
int p[MAX];
int m[MAX][MAX];
int n;

void  matrix()
{
    int i,j,r,k;
    memset(m,0,sizeof(m));
    for(r = 2; r<=n; r++)
    {
        for(i = 1; i<=n-r+1; i++)
        {
            j = i+r-1;
            m[i][j] = m[i+1][j]+p[i-1]*p[i]*p[j];
            for(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;
                }
            }
        }
    }
}

int main()
{
    cin>>n;
    //记录输入的数字,注意个数比n多1
    for(int i=0; i<n+1; i++)
        cin>>p[i];
    matrix();
    cout<<m[1][n];
    return 0;
}

for(r = 2; r<=n; r++):外层循环,从r=2开始遍历到n,表示矩阵链的长度。

for(i = 1; i<=n-r+1; i++):内层循环,从i=1开始遍历到n-r+1,表示矩阵链的起始位置。

j = i+r-1;:计算矩阵链的结束位置。

m[i][j] = m[i+1][j]+p[i-1]*p[i]*p[j];:根据动态规划的递推关系式,计算m[i][j]的最优值。

for(k = i+1; k<j; k++):再次遍历矩阵链中的每个矩阵,寻找最优值。

int t = m[i][k] +m[k+1][j]+p[i-1]*p[k]*p[j];:计算当前划分位置k时的最优值。

if(t<m[i][j]):如果当前最优值t小于m[i][j],更新m[i][j]为t。

这5个矩阵连乘有多少个可能:11

 心得

动态规划问题需要找出递归方程式,设计好所需要填的表格及行列所代表的意义

 
...全文
65 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

434

社区成员

发帖
与我相关
我的任务
社区描述
广东外语外贸大学信息科学与技术学院
算法 高校
社区管理员
  • brisksea
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧