851-动态规划

本文探讨了动态规划在解决矩阵连乘问题中的应用,通过矩阵链的最优计算量和分割点求解算法,实现计算效率的最大化。同时介绍了动态规划在凸三角形最优三角剖分问题中的运用,以及最长公共子序列、01背包问题和最大子段和等经典问题的解决方案,展示了动态规划在解决复杂计算问题上的强大能力。
摘要由CSDN通过智能技术生成

动态规划概念:动态规划与分治法类似,其基本思想是将求解问题分解成若干子问题,先求解子问题,再结合这些子问题的解得到原问题的解。与分治法不同的是,适合用动态规划求解的问题经分解得到的子问题往往是不相互独立的。
在这里插入图片描述

矩阵连乘

问题描述:给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的(i=1,2,…,n-1)。考察这n个矩阵的连乘积A1A2…An。求n个矩阵求其最优解。
在这里插入图片描述

//计算最优值
void Matrixchain(int *p,int n,int **m,int **s){     //m[i][j]表示从i到j的最优计算量,s[i][j]表示从i到j的最优分割点
    for(int i=1;i<=n;i++){       //边界条件,当只有一个矩阵时,最优计算量为0
        m[i][i]=0;
    }
    for(int r=2;i<=n;r++){      //r表示链长,当链长为n的时候,即最终结果从i到j的最优分割点和最优计算量
        for(int 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];     //计算初始从i到j当分隔点为i时的初始最优解
            s[i][j]=i;
            for(int k=i+1;k<j;k++){         //寻求m[i][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;
                }
            }
        }
    }
}

//构造最优解
void Traceback(int i,int j,int **s){
    if(i==j)    //当i等于j的时候为边界条件,此时只有一个矩阵是最优解
        return;
    Traceback(i,s[i][j],s);
    Traceback(s[i][j+1],j,s);
    printf("Multiply A %d,%d"i,s[i][j]);
    printf("And A %d,%d"s[i][j]+1,j);
}

凸三角形最优三角剖分

在这里插入图片描述
在这里插入图片描述
算法思想:用递推的思想求出,最优三角形剖分
主体思想:初始将凸多边形中含三个顶点时的解进行遍历求出顶点为三个时的优解,然后再将顶点数增加依次求出凸多边形中含4个顶点的最优解,5个顶点的最优解直到求出含全部顶点的最优解。
具体实现:将t【i】【j】看作由顶点i-1到顶点j的最优计算量
其中t【i】【j】=t【i,k】+t【k+1】【j】+w(i-1,k,j)表示将顶点以k为(中间点)分割点的最优计算量
递归关系:边界条件为 i=j 当i-j时,只含二个顶点权值为0;
i<j时,t【i】【j】=min{ t【i,k】+t【k+1】【j】+w(i-1,k,j)} 其中w(i,k,j)
表示以k为中间点(分割点)|vivk|+|vjvk|+|vkvi|的距离之和。

void MinSjpf(int n,int **t,int **s){
    for(i=1;i<=n;i++){  //边界条件,当只有二个顶点时,无法构成三角形,周长为0,故初始化为0
        t[i][i]=0;      //注意t[1][1]表示从第0个顶点到第1个顶点二个顶点,t[i][j]表示从第i-1个顶点到第j个顶点
    }
    for(int r=2;r<=n;r++){  //r=2时表示三个顶点
        for(int i=1;i<n-r+1;i++){
            j=i+r-1;
            t[i][j]=t[i+1][j]+w(i-1,i,j);
            s[i][j]=i;
            for(int k=i+1;k<j;k++){
                int u=t[i,k]+t[k,j]+w(i-1,k,j);
                if(u<t[i][j]){
                    t[i][j]=u;
                    s[i][j]=k;
                }
            }
        }
    }
}

最长公共子序列

0 1 背包

最大子段和

电路布线

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值