动态规划解决矩阵链乘最优顺序问题

问题描述与算法描述见《算法导论》,算法实现代码如下:
// 矩阵链乘最优解
#include <stdio.h>
#include 
<limits.h>
#include 
<memory.h>

// 计算辅助表
// 输入: 矩阵维数数组p[n+1]
// 输出: 辅助表m[i, j], s[i, j]
void matrix_chain_order(int p[], int length, int **m, int **s)
{
    
int N = length;
    
for (int i=0; i<N; ++i)
    
{
        m[i][i] 
= 0;                                    // 长度为1的矩阵链,标量乘法运算次数为0
    }


    
for (int L=2; L<=N; ++L)                // L是矩阵链长度
    {
        
for (int i=0; i<N-L+1++i)            // 矩阵链起始下标
        {
            
int j=i+L-1;                            // 矩阵链结尾下标
            m[i][j] = INT_MAX;                // 初始设定为无穷大(用INT_MAX表示)
            
            
for (int k=i; k<j; ++k)            // 从k处将矩阵链一分为二
            {
                
int q = m[i][k] + m[k+1][j] + p[i] * p[k+1* p[j+1];
                
if (q < m[i][j])
                
{
                    m[i][j] 
= q;
                    s[i][j] 
= k;
                }

            }

        }

    }

}


// 构造最优解
void print_optimal_parens(int **s, int i, int j)
{
    
if (i==j)
    
{
        putchar(
'A');
        putchar(
'1' + i);
    }

    
else
    
{
        putchar(
'(');
        print_optimal_parens(s, i, s[i][j]);
        print_optimal_parens(s, s[i][j] 
+ 1, j);
        putchar(
')');
    }

}


// 打印矩阵
void print_matrix(int **m, int n)
{
    
for (int i=0; i<n; ++i)
    
{
        
for (int j=0; j<n; ++j)
        
{
            printf(
"%d ", m[i][j]);
        }

        printf(
" ");
    }

}


int main()
{
    
int p[] = {3035155102025};
    
//int p[] = {5, 10, 3, 12, 5, 50, 6};
    int n = sizeof(p)/sizeof(int- 1;

    
int **= new int*[n];
    
for (int i=0; i<n; ++i)
    
{
        m[i] 
= new int[n];
        memset(m[i], 
0sizeof(int)*n);
    }


    
int **= new int*[n];
    
for (int i=0; i<n; ++i)
    
{
        s[i] 
= new int[n];
        memset(s[i], 
0sizeof(int)*n);
    }


    matrix_chain_order(p, n, m, s);

    printf(
"m[i, j]:  ");
    print_matrix(m, n);
    printf(
"s[i, j]:  ");
    print_matrix(s, n);

    print_optimal_parens(s, 
05);
    printf(
" ");

    
for (int i=0; i<n; ++i)
    
{
        delete [] m[i];
    }

    delete [] m;

    
for (int i=0; i<n; ++i)
    
{
        delete [] s[i];
    }

    delete [] s;
    
    
return 0;
}

/*
测试
输入:{30, 35, 15, 5, 10, 20, 25}
输出:
m[i, j]:
0            15750        7875        9375        11875        15125
0            0                2625        4375        7125        10500
0            0                0                750            2500        5375
0            0                0                0                1000        3500
0            0                0                0                0                5000
0            0                0                0                0                0
s[i, j]:
0            0            0            2            2            2
0            0            1            2            2            2
0            0            0            2            2            2
0            0            0            0            3            4
0            0            0            0            0            4
0            0            0            0            0            0
((A1(A2A3))((A4A5)A6))
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值