区间dp

合并类动态规划

  • 合并:意思就是将两个或多个部分进行整合,当然也可以反过来,也就是是将一个问题进行分解成两个或多个部分。
  • 特征:能将问题分解成为两两合并的形式
  • 求解:对整个问题设最优值,枚举合并点,将问题分解成为左右两个部分,最后将左右两个部分的最优值进行合并得到原问题的最优值。有点类似分治算法的解题思想。
  • 典型试题:整数划分,凸多边形划分、石子合并、多边形合并、能量项链等。
  • 主要思路:将整区间分成所有可以分成的小区间,依次遍历求最小最大值。

普遍模板:

for(int len=1; len<=n; len++){ //依次遍历区间长度
        for(int i=1; i+len-1<=n; i++){
            int j = i + len - 1; //i为区间起点,j为终点
            for(int k=i; k<j; k++){
                f[i][j] = min/max(f[i][j], f[i][k]+f[k+1][j]+a[k]);
            }
        }
    }

例题

样例输入:

4
4 5 9 4

样例输出:

44
54

解:

  #include<bits/stdc++.h>
using namespace std;

const int N = 110;

int n;
int f[N][N], g[N][N];
int a[N], s[N];

int main(){

    scanf("%d",&n);
    for(int i=1; i<=n; i++){
        scanf("%d", &a[i]);
        s[i] = s[i-1] + a[i]; //前缀和预处理
    }

    memset(f, 0x3f, sizeof(f));
    
    for(int i=1; i<=n; i++) f[i][i] = 0;

    for(int len=1; len<=n; len++){
        for(int i=1; i+len-1<=n; i++){
            int j = i + len - 1;
            for(int k=i; k<j; k++){
                f[i][j] = min(f[i][j], f[i][k]+f[k+1][j]+s[j]-s[i-1]);
                g[i][j] = max(g[i][j], g[i][k]+g[k+1][j]+s[j]-s[i-1]);
            }
        }
    }
    printf("%d\n", f[1][n]);
    printf("%d\n", g[1][n]);

    return 0;
}
posted @   Aqr_Rn  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示