惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
Cisco Talos Blog
Cisco Talos Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
V2EX
博客园 - 三生石上(FineUI控件)
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学
D
Docker
S
SegmentFault 最新的问题
博客园 - 聂微东
美团技术团队
Apple Machine Learning Research
Apple Machine Learning Research
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Last Week in AI
Last Week in AI
M
MIT News - Artificial intelligence
F
Fortinet All Blogs
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The GitHub Blog
The GitHub Blog
GbyAI
GbyAI
L
LangChain Blog
Vercel News
Vercel News
博客园 - 叶小钗
MongoDB | Blog
MongoDB | Blog
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
Engineering at Meta
Engineering at Meta
T
Threat Research - Cisco Blogs
T
Threatpost
Scott Helme
Scott Helme
T
Tailwind CSS Blog
Latest news
Latest news
Stack Overflow Blog
Stack Overflow Blog
Blog — PlanetScale
Blog — PlanetScale
The Register - Security
The Register - Security
罗磊的独立博客
P
Proofpoint News Feed
腾讯CDC
S
Schneier on Security
雷峰网
雷峰网
A
About on SuperTechFans
T
Tenable Blog
F
Full Disclosure
Cyberwarzone
Cyberwarzone
博客园_首页
有赞技术团队
有赞技术团队
K
Kaspersky official blog

文章列表

5月月考 - faryou的博客 - 日记 faryou的博客-五一回老家 【汇编 - 功能】中断安装中断实现 【汇编&硬件】时钟中断的具体实现 faryou的博客-这些年,我不再看《熊出没》 【汇编&硬件】关机中断的具体实现 【汇编&硬件】网络连接相关中断的具体实现 faryou的博客-年初小记 【汇编&硬件】鼠标控制中断的具体实现 【汇编&硬件】声音输出中断的具体实现 【汇编&硬件】屏幕输出中断的具体实现 【汇编&硬件】磁盘读取中断的具体实现 【汇编&硬件】键盘读取中断的具体实现 【汇编】汇编环境的搭建及Debug的使用教程 【汇编】漫谈:学习汇编后的一些思考 faryou的博客-关于本站即日起实行“一站三体”运营制度 【汇编基础教程】完结篇 写在最后:前言 【汇编基础教程】使用BIOS的中断实现键盘输入及磁盘I/O 【汇编基础教程】中断 【汇编基础教程】端口 【汇编基础教程】标志寄存器 【汇编基础教程】寄存器和内存&一些基本命令的说明 【汇编基础教程】来存一些数据! 【汇编基础教程】段 【汇编基础教程】再谈栈 【汇编基础教程】来写个“函数” 【汇编基础教程】理解一下[bx]和loop指令 【汇编基础教程】更灵活的定位内存 【汇编基础教程】跳一跳! faryou的博客-我的竞赛经历&对人生的一些思考 faryou的博客-关于现在中小学计算机课的一些想法及思考 faryou的博客-2025年度总结 faryou的博客-临平山下十五年 faryou的博客-Windows 10即将停止支持,谈谈自己从小到大用电脑的感受 faryou的博客-谈谈一名10后的怀旧情怀 【汇编基础教程】8086CPU工作原理 【C语言】指针的理解与应用 【算法教程】【C/C++】BFS(广度优先搜索)——程序设计思路与代码实现 【算法教程】【C/C++】DFS(深度优先搜索)——程序设计思路与代码实现 【算法教程】【C/C++】单源最短路径——程序设计思路与代码实现 【算法教程】【C/C++】最小生成树——程序设计思路与代码实现 【算法教程】【C/C++】并查集——程序设计思路与代码实现
【算法教程】【C/C++】DP(动态规划):区间DP——程序设计思路与代码实现
faryou · 2025-07-30 · via

前言
今天我们学习另一种DP——区间DP。

程序设计思路
(由于无法从概念上描述题意,这里直接放题目~)
202409081725774600907409.png
题意很好理解,要求我们求出合并所有石堆的最小代价。
首先思考一维DP式,很容易想到将dp[i]定义为合并从第一堆石子到第i堆石子所花费的代价。但是,状态转移方程怎么办?!由于本题中合并的顺序不唯一,第一堆石子也有可能最后合并,所以这个方法不可行。
这个时候我们需要思考一下:某个区间的最小代价一定是这个区间分为2个区间后这两个区间的代价之和。这样我们可以得到二维DP的定义:dpi代表从第i堆到第j堆石子合并所需要的最小代价。然后再思考,不难得到:我们可以对某个区间进行分割,这个分割点就是我们要去找的。故我们可以列出以下方程:dpi=min(dpi,dpi+dpi+k+1+s[j]-s[i-1](s[i]为从第一堆石子到第i堆石子代价的前缀和,用来累加代价,自行理解,另外需要预处理)。最后一个问题:dpi如何初始化?首先如果只有一堆那合并的代价为0,故dpi=0,而由于我们求最小代价,dp[i]j可以初始化成一个很大的数,方便比较操作。

代码实现

#include <stdio.h>
#include <memory.h>
//今天想重温一下C语言,故用C语言
int n,m[1001],dp[1001][1001],s[1001];//均如题意或已讲解

int min(int a,int b){//C语言没有min函数,所以手搓一个
    if(a<b) return a;
    else return b;
}

main(){
    scanf("%d",&n);
    memset(s,0,sizeof(s));
    memset(dp,0x3f3f3f3f,sizeof(dp));//初始化为大数
    for(int i=1;i<=n;i++) dp[i][i]=0;
    for(int i=1;i<=n;i++) scanf("%d",&m[i]);
    for(int i=1;i<=n;i++) s[i]=m[i]+s[i-1];//计算前缀和
    for(int len=1;len<=n;len++) for(int i=1;i<=n;i++){//len为长度,先计算长度为1的区间之后逐渐累加并重叠
        int j=i+len-1;
        if(j>n) break;//防越界
        for(int k=0;k<len;k++) dp[i][j]=min(dp[i][j],dp[i][i+k]+dp[i+k+1][j]+s[j]-s[i-1]);//dp式
    }
    printf("%d",dp[1][n]);
    return 0;
}

可以看到,区间DP的代码很简洁,所以重在理解~

结语
区间DP没有变式,其O(n3)的时间复杂度也无法进行优化,理解即可。我是faryou,再见!