动态规划算法解矩阵连乘

当前编程题:动态规划算法解矩阵连乘(动态规划)—动态规划算法解矩阵连乘(动态规划)

【问题描述】使用动态规划算法解矩阵连乘问题,具体来说就是,依据其递归式自底向上的方式进行计算,在计算过程中,保存已子问题答案,每个子问题只解决一次,在后面计算需要时只要简单查一下得到其结果,从而避免大量的重复计算,最终得到多项式时间的算法。

【输入形式】在屏幕上输入矩阵连乘个数,和第1个矩阵的行数和第1个矩阵到第n个矩阵的列数,各数间都以一个空格分隔。

【输出形式】矩阵m,其中m(i,j)中存放的是:计算Ai:j所需的最少数乘次数。矩阵s,其中s[i][j]记录了断开的位置,即最优的加括号方式应为(A[i:s[i][j]])*(A[s[i][j]+1:j])。矩阵连乘A1…An的最优计算次序。

【样例输入】

6

30 35 15 5 10 20 25

【样例输出】

[[ 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]]

[[0 1 1 3 3 3]

[0 0 2 3 3 3]

[0 0 0 3 3 3]

[0 0 0 0 4 5]

[0 0 0 0 0 5]

[0 0 0 0 0 0]]

((A1(A2A3))((A4A5)A6))

【样例说明】

输入:矩阵连乘个数为6,第1个矩阵的行数和第1个矩阵到第n个矩阵的列数,以空格分隔。

输出:矩阵m,s,和矩阵连乘的最优计算次序。

【评分标准】根据输入得到准确的输出。
python:

import numpy as np


def matrix_chain(p, n, s, m):
    for Len in range(2, n+1):
        for i in range(1, n-Len+2):
            j = i+Len-1
            m[i, j] = m[i+1, j] + p[i-1]*p[i]*p[j]
            s[i, j] = i
            for k in range(i+1, j):  # i+1
                q = m[i, k] + m[k+1, j] + p[i-1]*p[k]*p[j]
                if q < m[i, j]:
                    m[i, j] = q
                    s[i, j] = k


def print_optimal_parens(s, i, j):
    if i == j:
        print("A"+str(i), end='')  # end=''
    else:
        print("(", end='')
        print_optimal_parens(s, i, s[i, j])
        print_optimal_parens(s, s[i, j]+1, j)
        print(")", end='')


def main():
    n = int(input())
    p = np.array(list(map(int, input().split())))
    m = np.zeros([n+1, n+1], dtype=int)
    s = np.zeros([n+1, n+1], dtype=int)
    matrix_chain(p, n, s, m)
    print(m[1:n+1, 1:n+1])
    print(s[1:n+1, 1:n+1])
    print_optimal_parens(s, 1, n)


if __name__ == '__main__':
    main()

C++:

#include<iostream>
using namespace std;
const int MAX=1000;
int p[MAX+1];  //记录相邻矩阵的行列值
int m[MAX][MAX];  //记录数乘次数最优解 最终解值为m[1][n];
int s[MAX][MAX];  //记录划分括号位置 
int n; 
void Matrix_chain(){
    for(int i=1;i<=n;i++) 
		m[i][i]=0;
    for(int r=2;r<=n;r++)
        for(int i=1;i<=n-r+1;i++){
            int j=r+i-1;
            m[i][j]=m[i][i]+m[i+1][j]+p[i-1]*p[i]*p[j];
            s[i][j]=i;   
            for(int k=i+1; k<j; k++){
                int temp=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j];
                if(temp<m[i][j]){
                    m[i][j]=temp;
                    s[i][j]=k;
                }
            }
        }
}
void Print_optimal_parens(int i,int j){ 
    if(i==j) 
		cout<<"A"<<i;
    else{
    	cout<<"(";
	    Print_optimal_parens(i,s[i][j]);
	    Print_optimal_parens(s[i][j]+1,j);
	    cout<<")";
	}
}
int main(){
    cin>>n;
    for(int i=0;i<=n;i++)
        cin>>p[i];
    Matrix_chain();
   
    for(int i=1;i<=n;i++){
    	for(int j=1;j<=n;j++)
    		cout<<m[i][j]<<" ";
    	cout<<endl;
	}
	cout<<endl;
    for(int i=1;i<=n;i++){
    	for(int j=1;j<=n;j++)
    		cout<<s[i][j]<<" ";
    	cout<<endl;
	}	
    Print_optimal_parens(1,n);
    return 0;
}

老师的参考代码:

import numpy as np


def dynamic_matrix_chain(p, n):
    m = np.zeros((n+1, n+1), dtype=np.double)
    s = np.zeros((n+1, n+1), dtype=np.int8)
    for len in range(2, n+1):
        for i in range(1, n-len+2):
            j = i+len-1
            m[i, j] = np.inf
            for k in range(i, j):
                q = m[i, k]+m[k+1, j]+p[i-1]*p[i]*p[j]
                if q < m[i, j]:
                    m[i, j] = q
                    s[i, j] = k
    return m, s


def print_optimal_parens(s, i, j):
    if i == j:
        print("A%d" % i, end="")
    else:
        print("(", end="")
        print_optimal_parens(s, i, s[i, j])
        print_optimal_parens(s, s[i, j]+1, j)
        print(")", end="")


def main():
    n = int(input())
    p = input().split()
    p = np.array(p, dtype=np.double)
    m, s = dynamic_matrix_chain(p, n)
    m = m.astype(int)
    print(m[1:, 1:])
    print(s[1:, 1:])
    print_optimal_parens(s, 1, n)


if __name__ == '__main__':
    main()

发布了110 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_40486952/article/details/88697111