POJ-1651 Multiplication Puzzle 矩阵连乘问题(区间dp)
題意
給我們n個數(shù) 讓我們隨意的跳出其中的數(shù) 每挑出一個數(shù) 計算代價為左邊數(shù)* 當前數(shù) * 右邊的數(shù)
除了首尾兩個數(shù)不選 中間的數(shù)可以任意挑 讓我們求最小代價
CODE
#include<bits/stdc++.h> using namespace std; int a[110],m[110][110]; const int maxn = 0x7f7f7f; int main() {int n;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);for(int i=1;i<=n;i++)m[i][i]=0;for(int l=2;l<n;l++){// 區(qū)間長度從2開始 1沒意義 for(int i=1;i<=n-l+1;i++){// 起始點從2 開始 int j = i+l-1;m[i][j] = maxn;// cout<<"L:"<<l<<" "<<i<<" "<<j<<":"<<endl;for(int k = i;k<j;k++){// 枚舉最后一個選擇的位置 int t = m[i][k]+m[k+1][j]+a[i-1]*a[k]*a[j];//本次結(jié)果就是從i到k連起來的最小+從k+1到j(luò)連起來的最小+本次連起來后的代價 // cout<<i-1<<" "<<k<<" "<<j<<" "<<t<<endl;m[i][j] = min(t,m[i][j]);// system("pause");}}}printf("%d\n",m[2][n]);return 0; }分析
這道題開始看非常蒙
這該怎么做?
其實這道題可以轉(zhuǎn)化成矩陣連乘問題
我們定義從i到j(luò)的最小代價 其實就是從i 到k + 從k+1 到j(luò)的最小代價 + 中間分割的k的代價 把i到j(luò)之間的k枚舉一遍取最小
所以就得到了兩個子問題
我們知道兩個矩陣相乘總計算量就是p* r * q(p*r,r * q的兩個矩陣)
有沒有發(fā)現(xiàn)這里有點相似
每相鄰的兩個數(shù) 就是矩陣的行和列
第i個矩陣式子為 a[i-1]*a[i]
所以從起始點從2開始才有意義
如果其實點從1開始沒意義(a[i-1]為0 那么計算量為0)
第一個矩陣為前兩個元素 開始那么他的參數(shù)就是
a[1]?a[2]
所以這道題我們刪掉一個元素時 或是從中心合并兩個結(jié)果時
加上額外的代價
也就是a[i?1]?a[k]?a[j]
這個就是 、
第一個矩陣 a[i?1]?a[k]
第二個矩陣a[k]?a[j]
那么其抽象計算量就是
a[i?1]?a[k]?a[j]
就相當于兩個矩陣相乘的總計算量
所以下標從2開始有意義
例如 3
1 2 3
抽象成矩陣為 1×2 2×3
那么 答案就是 dp[2][n]
左邊起始有意義的點為2 右邊結(jié)束點其實就是n
為什么是n呢 因為如果不把n算在內(nèi) 最終我們循環(huán)的
最大的j就是n 如果不考慮n 那么說明我們沒考慮最后一個矩陣的最后一個參數(shù)
所以必須要時dp[2][n]
將原序列拆解后的矩陣序列
這道題其實就是相當于考慮剩余首尾兩個元素
其余的全部拿出來的最小代價
注意第n個元素要算到第n-1個的計算量中 所以第n個元素在矩陣問題中就是最后一個參數(shù)
這個參數(shù)是要合并的
如果全取
我們所要輸出就是dp[1][n+1]了
這個問題之所以可以抽象成矩陣問題
因為我們要提出2-n-1的數(shù) 然而在計算的過程中卻把1和n也以a[i?1]?a[k]?a[j]的形式算進去了
也就是能夠表示出矩陣計算量
總結(jié)
以上是生活随笔為你收集整理的POJ-1651 Multiplication Puzzle 矩阵连乘问题(区间dp)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: AMESim 14.0 win10环境下
- 下一篇: 基于.Net Framework 4.0