( 动态规划专题 )【 区间dp 】

( 动态规划专题 )【 区间dp 】

 推荐:https://blog.csdn.net/qq_40772692/article/details/80183248

一.什么是区间dp?

顾名思义:区间dp就是在区间上进行动态规划,求解一段区间上的最优解。主要是通过合并小区间的 最优解进而得出整个大区间上最优解的dp算法。

二.核心思路

既然让我求解在一个区间上的最优解,那么我把这个区间分割成一个个小区间,求解每个小区间的最优解,再合并小区间得到大区间即可。所以在代码实现上,我可以枚举区间长度len为每次分割成的小区间长度(由短到长不断合并),内层枚举该长度下可以的起点,自然终点也就明了了。然后在这个起点终点之间枚举分割点,求解这段小区间在某个分割点下的最优解。

板子:

    for(int len = 1; len<=n; len++) {//枚举长度
        for(int i = 1; i+len-1<=n; i++) {//枚举起点,ends<=n
            int ends = i+len-1;
            for(int j=i; j

三 朴素区间dp(n^3)

例题:石子归并1

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

样例: 4 1 2 3 4  -->   19

传送门:戳我呀

转移方程:

dp[i][ends] = min(dp[i][ends],dp[i][j]+dp[j+1][ends]+weigth[i][ends]);

j~ends堆合并 = 较小的(原来, 分割点i坐部分重量 + 分割点i右边部分重量 + 合并后两堆总重量)

注:可以用sum[j] - sum[i - 1]表示i~j堆的重量!

代码:

#include
#define int long long

using namespace std;

const int maxn = 102;
int sum[maxn];
int a[maxn],dp[maxn][maxn],n;

signed main()
{
    memset(dp,0x3f3f3f3f,sizeof(dp));
    cin>>n;
    for ( int i=1; i<=n; i++ ) {
        scanf("%lld",&a[i]);
        sum[i] = sum[i-1]+a[i];
        dp[i][i] = 0;
    }
    for ( int len=1; len<=n; len++ ) {
        for ( int i=1; i+len-1<=n; i++ ) {
            int ends = i+len-1;
            for ( int j=i; j

 

你可能感兴趣的:(算法树之动态规划)