区间DP

区间DP

1.区间DP简介

区间型动态规划是线性动态规划的拓展,它将区间长度
作为阶段,长区间的答案与短区间有关。

在求解长区间答案前需先将短区间答案求出。

区间型动态规划的典型应用有石子合并、乘积最大等。

2.经典例题:石子合并

题目描述

在一个操场上一排地摆放着 N 堆石子。现要将石子有次序地合并成一堆。规定每次只能选相邻的 2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分。

计算出将 N 堆石子合并成一堆的最小得分。

输入

第一行为一个正整数 N

以下 N 行,每行一个正整数,分别表示第 i 堆石子的个数 (1iN)

输出

一个正整数,即最小得分。

输入样例

7
13
7
8
16
21
4
18

输出样例

239

数据范围

2N100
0 每堆石子的数量 10000

注:本题来自信息学奥赛一本通第1274题

3.经典例题思路

还是一样,我们先来设 f 数组:

所有将第 i 堆石子到第 j 堆石子合并成一堆的最小合并方式

在状态计算方面,我们可以把每一堆石子分成两个区间。

每次都枚举一个 k,左区间有 1 个元素,右区间就有 k1 个元素;左区间有 2 个元素,右区间就有 k2 个元素,以此类推……

通过这一点,我们就可以用左区间的最小得分加上右区间的最小得分,再加上合并左区间和右区间的得分来推出每个区间的最小值。

所以,状态转移方程为:

f[i][j]=min(f[i][k]+f[k+1][j]+s[j]s[i1])

注1:k 是从 i 枚举到 j1

注2:此处 s 数组是前缀和数组,即 s[i] 为 开始元素一直加到第 i 个元素的值

4.经典例题代码(注释已全部标出)

#include<iostream>
using namespace std;
const int N=305;
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++)//要枚举的区间长度,因为len=1的情况结果为0,所以代码中不用体现
for(int i=1;i+len-1<=n;i++){//左区间位置
int l=i,r=i+len-1;//区间的左端和右端
f[l][r]=1e8;//每次都要初始化,要不然就全是0
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",f[1][n]);
return 0;
}

完awa~

如果觉得还行,就点个赞吧,您的支持对我来说很重要,谢谢。

posted @   Rainforests  阅读(48)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示