DP - 區間DP - Multiplication Puzzle - POJ - 1651
題意:
給定一個長度爲n的序列w,可以去除一個數wi,i∈[2,n−1],代價爲wi−1×wi×wi+1。
最終要使得序列僅剩下首尾兩個元素w1和wn,問最小代價是多少。
分析:
與——《NOIP 2006 - 能量項鍊》類似,區別在不選第一個元素和最後一個元素,而且序列是鏈形不是環形,類似於矩陣連乘問題。
狀態表示f[l][r]:將區間[l,r]變成wl和wr所需花費的最小代價。
狀態計算:區間[l,r]可分爲兩部分[l,k],[k,r],再加去掉wk的代價。即:f[l][r]=min(f[l][k]+f[k][r]+wi−1×wi×wi+1),k∈[l+1,r−1]。
注意:
由於要求最小代價,那麼數組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;
}