間隔dpの原則

インターバル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 [ l1 ] 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;
}

おすすめ

転載: blog.csdn.net/zzq0523/article/details/113100651