動態規劃--矩陣連乘
阿新 • • 發佈:2019-02-11
#include<iostream> using namespace std; //無論括號怎麼分這些連續相乘的矩陣,最後括號都可以歸結到只有兩對括號,把整個連乘的矩陣分成兩部分 // / 0 i==j //m[i][j] = // \ min{ m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j] } i<j, i<=k<j //遞迴計算矩陣連乘 int liancheng(int i, int j, int *p, int **s) { if (i == j) return 0; int MIN = liancheng(i, i, p, s) + liancheng(i + 1, j, p, s) + p[i - 1] * p[i] * p[j]; s[i][j] = i; for (int k = i+1; k < j; k++) { int rlt = liancheng(i, k, p, s) + liancheng(k+1, j, p, s) + p[i-1]*p[k]*p[j]; if(rlt < MIN) { MIN = rlt; s[i][j] = k; } } return MIN; } int MatrixChain(int *p, int n, int **m, int **s) { for (int i = 1; i <= n; i++) m[i][i] = 0; //單個矩陣,計算次數為0 for (int r = 2; r <= n; r++) { //代表幾個矩陣連乘 for (int i = 1; i <= n - r + 1; i++) { //i<=n-r+1是怎麼得來的? i+r-1<=n int j = i + r - 1;//r個矩陣相乘,最後一個矩陣的座標為j m[i][j] = m[i][i] + m[i + 1][j] + p[i - 1]*p[i]*p[j]; //把第一種m[i][j]的值當成是目前最小的,i也就是第一次k的位置 s[i][j] = i; //為了求m[i][j]的所有情況中的最小值 for (int k = i + 1; k < j; k++) { //因為上面已經計算了k=i的情況,所以繼續往下計算的話,就計算k=i+1,這個地方的k一定是小於j的,不能等於j 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; } } } } return m[1][n]; } //求最優解,求出加括號的位置 void TraceBack(int i, int j, int **s) { if(i == j) return; cout<<"a"<<i<<"~a"<<j<<" 把a"<<i<<"到a"<<s[i][j]<<"括起來, 把a"<<s[i][j]+1<<"到a"<<j<<"括起來"<<endl; TraceBack(i, s[i][j], s); TraceBack(s[i][j]+1, j, s); } //列印s陣列,記錄每個位置加括號的位置 void PrintS(int **s) { for(int i=1; i<=6; i++) { for(int j=1; j<=6; j++) { cout<<s[i][j]<<" "; } cout<<endl; } } int main() { //6個矩陣連乘 int p[7] = { 30, 35, 15, 5, 10, 20, 25 };//用來存放每個矩陣的行和列數,第一個矩陣的行列為p[0][1], 第二個為p[1][2],第三 //個為p[2][3],依此類推 int **m; //傳遞二級指標的時候,這樣做,直接int m[][],無法把m當作二級指標引數傳進去 m = (int **)new int[7]; for (int i = 0; i < 7; i++) { m[i] = (int *)new int[7]; } int **s; s = (int **)new int[7]; for(int i=0; i<7; i++) s[i] = (int *)new int[7]; cout << "遞迴結果: " << liancheng(1, 6, p, s) << endl; TraceBack(1, 6, s); for(int i=1; i<=6; i++) //清空s陣列 for(int j=1; j<=6; j++) s[i][j] = 0; cout << "動態規劃結果: "<<MatrixChain(p, 6, m, s) << endl; TraceBack(1, 6, s); return 0; }