インターバルDP
石の合併
石の山がN個並んでいて、その数は1、2、3、...、Nです。
石の各山には、整数で表すことができる特定の質量があります。次に、これらのN個の石の山を1つの山に結合する必要があります。
一度にマージできるのは、隣接する2つの杭のみです。マージのコストは、2つの石の山の質量の合計です。マージ後、2つの石の山に隣接する石は新しい杭に隣接します。合併時の選択順序が異なるため、合併の総費用も異なります。
問題は、総コストを最小限に抑え、最小のコストを出力するための合理的な方法を見つけることです。
状態表現
f [i] [j] f [i] [j] f [ i ] [ j ]すべてがiiになりますiからjjまでの石の山j石の山を石の山に組み合わせる方法
状態計算
f [l] [r] = M in(f [l] [r]、f [l] [k] + f [k + 1] [r] + s [r] − s [l − 1])f [l] [r] = Min(f [l] [r]、f [l] [k] + f [k + 1] [r] + s [r] -s [l-1]) f [ l ] [ r ]=M i n (f [ l ] [ r ] 、f [ l ] [ k ]+f [ k+1 ] [ r ] +s [ r ]−s [ l−1 ] ) kkとマージkは、境界の左右の間隔の最小コストに現在の間隔をマージするコストを加えたものです。
const int N = 305;
int s[N];
int f[N][N];
int main() {
int n;cin >> n;
for (int i = 1;i <= n;++i)cin >> s[i];
for (int i = 1; i <= n;++i)s[i] += s[i - 1];
for(int len = 2; len <= n ;++len){
//区间长度
for (int i = 1;i + len - 1 <= n;++i) {
//起点
int l = i, r = i + len - 1;//区间端点
f[l][r] = INF;
for (int k = l;k < r;++k) {
//枚举分界线
f[l][r] = min(f[l][r], f[l][k]+ f[k + 1][r] + s[r] - s[l - 1]);
}
}
}
cout << f[1][n];
return 0;
}