• 矩阵连乘问题(动态规划算法)


    动态规划算法思想简介:

    将一个问题分解为多个子问题,这点和分治法类似,但是每个子问题不是独立的而是相互联系的,所以我们在求解每个子问题的时候可能需要重复计算到其他的子问题,所以我们将计算过的子问题的解放进一个表中,这样就能避免了重复计算带来的耗费,这就是动态规划的基本思想;

    一般地,动态规划思想一般用来解最优化问题,主要分为以下四个步骤:

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

    (2)递归地定义最优值;

    (3)以自底向上的方式计算出最优值;

    (4)根据计算得到的最优值时得到的信息,构造最优解;

    同时,问题的最优子结构性质也是该问题可用动态规划算法求解的显著特征,这里的最优子结构性质即指:问题的最优解也即代表着它的子问题有了最优解;

    问题描述:

    具体可参考:https://blog.csdn.net/liufeng_king/article/details/8497607

    分析过程如下:

    (1)分析最优子结构的性质:

    (2)分析递归关系以及利用自底向上的方式进行计算:

    (3)获取最优值最优解

    代码如下:

    #ifndef MATRIX_CHAIN_H
    #define MATRIX_CHAIN_H
    
    void matrix_chain(int *p, int n, int **m, int **s);
    void traceback(int i, int j, int **s);
    
    #endif
    #include <iostream>
    #include "matrix_chain.h"
    
    using namespace std;
    
    //利用动态规划算法获取最优值
    void matrix_chain(int *p, int n, int **m, int **s)  //p:各个矩阵的列数,n:矩阵个数,m:m[i:j]矩阵i到j的相乘次数,s:对应的分开位置
    {
        for (int i = 0; i < n; i++)
        {
            m[i][i] = 0;
        }
        for (int r = 2; r <= n; r++)
        {
            for (int i = 0; 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;
                    }
                }
            }
        }
    }
    
    //利用s[i][j]获取最优解
    void traceback(int i, int j, int **s)
    {
        if (i == j)
            return;
        traceback(i, s[i][j], s);
        traceback(s[i][j] + 1, j, s);
        cout << "Multiply A" << i << " , " << s[i][j];
        cout << "and A" << (s[i][j] + 1) << " , " << j << endl;
    }
    #include <iostream>
    #include "matrix_chain.h"
    
    using namespace std;
    
    int main(void)
    {
        int matrix_num = 0;  //矩阵个数
        cout << "请输入矩阵个数:" << endl;
        cin >> matrix_num;
    
        int **m = new int *[matrix_num];
        for (int i = 0; i < matrix_num; i++)
            m[i] = new int[matrix_num];
        int **s = new int *[matrix_num];
        for (int i = 0; i < matrix_num; i++)
            s[i] = new int[matrix_num];
        int *p = new int[matrix_num];
        cout << "请输入各矩阵的列数:" << endl;
        for (int i = 0; i < matrix_num; i++)
        {
            cin >> p[i];
        }
    
        matrix_chain(p, matrix_num, m, s);
        traceback(0, matrix_num - 1, s);
    
        system("pause");
        return 1;
    }

     可结合我的另一篇关于贪心算法的博客进行比较,了解这两者的区别;

    (http://www.cnblogs.com/zf-blog/p/8674932.html)

  • 相关阅读:
    sql 笔记之一
    js的Location
    VS无法使用.XXXX附加到程序
    C#遍历对象的方法
    解决tomcat启动时中文乱码问题。
    动态sql foreach 循环报错问题
    java跳过https证书直接请求工具类
    安装svn报2503错误处理方法
    oracle常用的一些查询命令
    Oracle11g安装过程中忘记进行口令配置
  • 原文地址:https://www.cnblogs.com/zf-blog/p/8763090.html
Copyright © 2020-2023  润新知