DP - 區間DP - Multiplication Puzzle - POJ - 1651

DP - 區間DP - Multiplication Puzzle - POJ - 1651

題意:

nwwii[2,n1]wi1×wi×wi+1給定一個長度爲n的序列w,可以去除一個數w_i,i∈[2,n-1],代價爲w_{i-1}×w_i×w_{i+1}。

使w1wn最終要使得序列僅剩下首尾兩個元素w_1和w_n,問最小代價是多少。


分析:

與——《NOIP 2006 - 能量項鍊》類似,區別在不選第一個元素和最後一個元素,而且序列是鍊形不是環形,類似於矩陣連乘問題。

f[l][r]:[l,r]wlwr狀態表示f[l][r]:將區間[l,r]變成w_l和w_r所需花費的最小代價。

[l,r][l,k],[k,r],wkf[l][r]=min(f[l][k]+f[k][r]+wi1×wi×wi+1)k[l+1,r1]狀態計算:\\區間[l,r]可分爲兩部分[l,k],[k,r],再加去掉w_k的代價。\\即:f[l][r]=min(f[l][k]+f[k][r]+w_{i-1}×w_i×w_{i+1}),k∈[l+1,r-1]。

注意:

f20由於要求最小代價,那麼數組f初始化爲∞,但是長度小於等於2的區間代價爲0。

代碼:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>

using namespace std;

const int N=110;

int n,w[N],f[N][N];

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>w[i];
    
    memset(f,0x3f,sizeof f);
    for(int len=1;len<=n;len++)
        for(int l=1;l+len-1<=n;l++)
        {
            int r=l+len-1;
            if(len==1||len==2) f[l][r]=0;
            else
            for(int k=l+1;k<n;k++)
                f[l][r]=min(f[l][r],f[l][k]+f[k][r]+w[l]*w[k]*w[r]);
        }
    
    cout<<f[1][n]<<endl;
    
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章