Dp-区间dp:合并石子

在这里插入图片描述

/*
核心:最后一次合并一定是左边连续的一部分和右边连续的一部分进行合并

状态表示:f[i][j]
表示将 i 到 j

合并成一堆的方案的集合,属性 Min

状态计算:
(1) i<j
时,f[i][j]=mini≤k≤j−1f[i][k]+f[k+1][j]+s[j]−s[i−1]
(2) i=j 时, f[i][i]=0

(合并一堆石子代价为 0)

问题答案: f[1][n]

区间 DP 常用模版
所有的区间dp问题,第一维都是枚举区间长度,一般 len = 1 用来初始化,枚举从 len = 2 开始,第二维枚举起点 i (右端点 j 自动获得,j = i + len - 1)

*/

#include<iostream>
#include<algorithm>

using namespace std;

const int N=310;

int n;
int s[N];//存放前缀和
int f[N][N];//f[i][j]表示从第i堆到第j堆合并成一堆,花费的最小代价

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];
    
    //从小到大枚举区间长度,不能从前往后枚举
    //len是区间内石子堆的个数
    //len从2开始枚举,len为1的时候不用枚举,只有一堆嘛
    for(int len=2; len<= n; len++)
        for(int i=1;i+len-1<= n; i++)
        {
            int l=i, r=i+len-1;
            f[l][r]=1e8;//因为要算最小值,所以先初始化为正无穷
            //在l到r中间,选取可能的分界点,找到合并k两边两堆石子的最小值
            for(int k=l;k<r;k++)
                //合并l-k 和k+1到r 需要花费的代价是f[l][k]+f[k+1][r]+sum[l-k];
                f[l][r]=min(f[l][r], f[l][k]+f[k+1][r]+s[r]-s[l-1]);
        }
    
    printf("%d\n",f[1][n]);
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值