• image.png

    定义

  1. table[][] 用于转换字母到数字
  2. m[N][N][4] : m[i][j][1/2/3] 表示部分表达式从第i个乘数到第j个乘数 , 结果分别为a,b,c的加括号方式

    基础解

    • 当表达式长度为一时 :
      • m[i][i][] : 除了对应字母的最低维结果为1, 其余全0

        递归求解

  • 以a为例

    • m[i][j][1] = ∑ ( m[i][k-1][1] m[k][j][3] + m[i][k-1][2] m[k][j][3] + m[i][k-1][3] * m[k][j][1] )
    • k∈[i+1,j] , k表示最后求和的位置

      问题解

  • m[1][n][1]

    代码

    1. #include<stdio.h>
    2. const int N = 20;
    3. int table[4][4] = { {0,0,0,0},
    4. {0,2,2,1},
    5. {0,3,2,1},
    6. {0,1,3,3} };
    7. //存放表达式
    8. char CharExpression[N];
    9. int IntExpression[N];
    10. int expLen=0;
    11. int m[N][N][4] = {0};//m[i][j][1] 表示exp[i-j] 可以得到值为a,b,c 的加括号方式数
    12. //字母转换为对应数字
    13. int trans(char x) {
    14. if (x == 'a') {
    15. return 1;
    16. }else if (x == 'b') {
    17. return 2;
    18. }
    19. else if (x == 'c') {
    20. return 3;
    21. }
    22. }
    23. int main() {
    24. scanf("%s", CharExpression);//输入
    25. for (int i = 0; CharExpression[i]!='\0'; i++) {//获得长度
    26. expLen++;
    27. }
    28. for (int i = 1; i <= expLen; i++) {//转换
    29. IntExpression[i] = trans(CharExpression[i-1]);
    30. }
    31. //基础解 表达式长度为1
    32. for (int i = 1; i <= expLen; i++) {
    33. m[i][i][1] = 0;
    34. m[i][i][2] = 0;
    35. m[i][i][3] = 0;
    36. m[i][i][IntExpression[i]] = 1;
    37. }
    38. //动态规划
    39. for (int r = 2; r <= expLen; r++) {//表达式长度
    40. for (int s = 1; s <= expLen - r + 1; s++) {//表达式起点
    41. int e = s + r - 1;//表达式终点
    42. for (int k = s + 1; k <= e; k++) {//断点 k=s+1 表示分割[s:e] 为 [s] [s+1,...,e]
    43. m[s][e][1] += m[s][k - 1][1] * m[k][e][3] + m[s][k - 1][2] * m[k][e][3] + m[s][k - 1][3] * m[k][e][1];
    44. m[s][e][2] += m[s][k - 1][1] * m[k][e][1] + m[s][k - 1][1] * m[k][e][2] + m[s][k - 1][2] * m[k][e][2];
    45. m[s][e][3] += m[s][k - 1][2] * m[k][e][1] + m[s][k - 1][3] * m[k][e][2] + m[s][k - 1][3] * m[k][e][3];
    46. }
    47. }
    48. }
    49. printf("%d", m[1][expLen][1]);
    50. return 0;
    51. }