区间dp详解(入门到进阶)

本文详细介绍了区间动态规划(区间dp)的概念及其在不同问题中的应用,包括石子合并问题的初级、中级、高级和究极版本。通过实例解析了状态转移方程和优化策略,如四边形不等式、GarsiaWachs算法和平衡树优化,旨在帮助读者深入理解区间dp并提升解题能力。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

 

前言:

初级版:51Nod - 1021 石子合并(区间dp,时间复杂度)

思路:

状态转移方程:

AC代码:

中级版:HDU - 3506 Monkey Party(四边形不等式优化,时间复杂度)

思路:

四边形不等式:

状态转移方程:

AC代码:

高级版:HYSBZ - 3229 石子合并(GarsiaWachs算法优化,时间复杂度常数小)

思路:

AC代码:

究极版:POJ - 1738 An old Stone Game(GarsiaWachs算法优化+平衡树优化,时间复杂度)

思路:

AC代码:


前言:

区间dp主要用于解决是将小区间合并成大区间的一种算法,通过断点的转移来合并区间以达到状态转移。比如石子合并就是通过对前缀和的操作,通过左端点和控制区间长度来进行的。

题目链接请点击题目

初级版:51Nod - 1021 石子合并(区间dp,时间复杂度O(n^{3})

基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题

N堆石子摆成一条线。现要将石子有次序地合并成一堆。规定每次只能选相邻的2堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的代价。计算将N堆石子合并成一堆的最小代价。

 

例如: 1 2 3 4,有不少合并方法

1 2 3 4 => 3 3 4(3) => 6 4(9) => 10(19)

1 2 3 4 => 1 5 4(5) => 1 9(14) => 10(24)

1 2 3 4 => 1 2 7(7) => 3 7(10) => 10(20)

 

括号里面为总代价可以看出,第一种方法的代价最低,现在给出n堆石子的数量,计算最小合并代价。

Input

第1行:N(2 <= N <= 100)
第2 - N + 1:N堆石子的数量(1 <= A[i] <= 10000)

Output

输出最小合并代价

Input示例

4
1
2
3
4

Output示例

19

思路:

通过前缀和记录区间和的情况,然后通过区间dp求解。

状态转移方程:dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1])(k\in [i,j])

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 7;
const int inf = 0x3f3f3f3f;
int wight[N],dp[107][107],w;
int main()
{
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    memset(dp,inf,sizeof dp);
    memset(wight,0,sizeof wight);
    for(int i = 1;i <= n;++i){
        cin >> w;
        wight[i] = wight[i - 1] + w;
        dp[i][i] = 0;
    }
    for(int l = 1;l <= n;++l)
        for(int i = 1;i + l <= n;++i){
            int End = i + l;
            for(int j = i;j <= End;++j)
                dp[i][End] &
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值