• 设从矩阵Ai 到 Aj 的矩阵序列为 A[i:j] , m[][] 存放最小乘法次数 ,自底向上求解求解 , 即从子链长度为1 逐步求解子链长度为n的解

      • 当 i==j 时 , 不需要乘 , m[i][i] = 0

        • 自底向上求解问题的解 ,
          • 当子链长度为1的时候无需求解 , 及m[i][i] = 0
      • 当i != j时候, 需要根据子问题的解来计算当前解

        • m[i:j] = MIN{ m[i:k] +m[k+1] + ppp| k∈[i,j) }
          • 尝试当前子链A[i:j]的所有断点(遍历) , 获得当前问题的最优解
        • m[i:k] , 该子链长度小于m[i:j] 的长度 , 所以此时一定已经存在m[i:k]最优解
        • m[k+1:j] , 同上当前就是最优解
    1. /*
    2. 矩阵连乘问题-动态规划
    3. */
    4. #include<stdio.h>
    5. #include<stdlib.h>
    6. #include<time.h>
    7. //矩阵最大行/列 数
    8. const int MAXSIZE = 101;
    9. //矩阵最小的行/列 数
    10. const int MINSIZE = 2;
    11. //存放最优问题的断点
    12. int s[MAXSIZE][MAXSIZE];
    13. //存放子问题结果
    14. int m[MAXSIZE][MAXSIZE];
    15. //最多的矩阵的个数+1
    16. const int MNUM = 3;
    17. //存放可连乘矩阵的所有行列下标 , 由于 上一个矩阵的列等于下一个矩阵的行数
    18. //故第n个矩阵的 行数为p[n-1] 列数为p[n]
    19. int p[MNUM+1];
    20. int tt = 0;
    21. //输出问题解 可以省略最高维度的大小
    22. void printres(int l, int r, int s[][MAXSIZE],int flag) {
    23. if (l == r) {
    24. printf("%d:%d", p[l - 1], p[l]);
    25. return;
    26. }
    27. //printf("%d %d\n", l, r);
    28. //system("pause");
    29. if (flag) {
    30. printf("(");
    31. printres(l, s[l][r], s,0);
    32. printf(")(");
    33. printres(s[l][r] + 1, r, s,0);
    34. printf(")");
    35. }
    36. else {
    37. printf("[");
    38. printres(l, s[l][r], s,1);
    39. printf("][");
    40. printres(s[l][r] + 1, r, s,1);
    41. printf("]");
    42. }
    43. }
    44. //动归解决问题
    45. void solve() {
    46. //A[i][i] 的乘法次数为0
    47. for (int i = 1; i <= MNUM; i++) {
    48. m[i][i] = 0;
    49. }
    50. //矩阵连乘子链的长度从2增长
    51. for (int r = 2; r <= MNUM; r++) {
    52. //i为r长度子链的起始下标
    53. for (int i = 1; i <= MNUM - r + 1;i++) {
    54. //j为r长度子链的尾下标
    55. int j = i + r - 1;
    56. //k ∈[i:j)
    57. //先计算k = i 时的计算次数
    58. m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j];
    59. s[i][j] = i;
    60. for (int k = i + 1; k < j; k++) {
    61. int temp = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
    62. if (temp < m[i][j]) {
    63. s[i][j] = k;
    64. m[i][j] = temp;
    65. }
    66. }
    67. }
    68. }
    69. }
    70. int main()
    71. {
    72. while (1)
    73. {
    74. srand(time(NULL));
    75. for (int i = 0; i <= MNUM; i++) {
    76. //确定每个矩阵的行列数
    77. p[i] = (rand() % (MAXSIZE - MINSIZE))+MINSIZE;
    78. printf("%d ", p[i]);
    79. }
    80. printf("\n");
    81. /*
    82. p[0] = 10;
    83. p[1] = 100;
    84. p[2] = 5;
    85. p[3] = 50;
    86. for (int i = 0; i <= MNUM; i++) {
    87. printf("%d ", p[i]);
    88. }
    89. printf("\n");
    90. */
    91. solve();
    92. printres(1, MNUM, s,1);
    93. printf("最小乘法次数为 : %d\n", m[1][MNUM]);
    94. system("pause");
    95. }
    96. return 0;
    97. }
    98. /*
    99. p[0] - p[3] = 10 100 5 50
    100. */