最優矩陣鏈乘——NBUT 1003
阿新 • • 發佈:2018-12-13
思路:也是和紫書上的一樣,如果最後一次乘法是第k個,則從A1,A2,....Ak和Ak+1,Ak+2......An兩個子序列都是最優乘法了,所以我們只需保證兩個子結構最優,而子結構也是可以這樣劃分的,所以我們每次考慮的問題就是,把Ai,Ai+1...Aj乘起來的最少乘法次數,用dp[i][j]表示這個問題的值,有
dp[i][j]=min{dp[i][k]+dp[k+1][j]+pi-1*pk*pj}
關鍵是遞推的次序要搞明白,當時就沒做出來,還是參考大神的程式碼,按照j-i遞增的方向遞推,因為長區間的值依賴於短區間的值。具體實現還是需要斟酌一下的,程式碼如下:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> using namespace std; typedef long long ll; const int maxn=210; const int INF=0x3f3f3f3f; ll dp[maxn][maxn]; ll p[maxn]; /* 遞推方向如何寫還是比較難想的,長區間的值依賴於短區間, 所以遞推的方向為j-i的遞增方向,i為集合左端,j為集合右端。 */ int main() { ll n; while(scanf("%lld",&n)!=EOF) { for(int i=0;i<n+1;i++) { scanf("%lld",&p[i]); } //長度為1的矩陣集合,都歸0,沒有乘法計算。 for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { if(i==j) dp[i][j]==0; } } for(int x=2;x<=n;x++)//矩陣集合的長度,2,3....n { for(int i=1;i<=n-x+1;i++) { //按照j-i遞增的順序遞推,因為j是矩陣集合的右端,而長區間的值依賴於短區間 int j=x+i-1; dp[i][j]=INF; for(int k=i;k<j;k++) { dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[j]); } } } printf("%lld\n",dp[1][n]); } return 0; }