区间 dp 石头合并

Snipaste_2024-01-29_21-38-55.png

输入样例
4
1 3 5 2
输出样例
22

(区间 dp)

Snipaste_2024-01-29_20-59-31.png

集合表示最后一次合并选区间中的哪个点作为分界点

状态转义方程 f[l][r] = min(f[l][r], f[l][k] + f[k+1][r] + s[r] - s[l - 1])

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 310;

int n;
int s[N];
int f[N][N];

int main(){
    
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d", &s[i]);
    
    // 初始化前缀和
    for(int i = 1; i <= n; i++) s[i] += s[i-1];
    
    for(int len = 2; len <= n; len++) // 枚举一次合并的堆的个数  因为 将一堆合并成一堆需要的 0
        for(int i = 1; i + len - 1 <= n; i++)
        {
            int l = i, r= i + len - 1; // 区间的左右端点
            f[l][r] = 1e8;  // 初始化为 无穷大
            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]);
        }
        
    printf("%d\n", f[1][n]);
    
    return 0;
}
posted @ 2024-01-29 21:41  TomLove  阅读(22)  评论(0)    收藏  举报