【动态规划 区间dp】Contest Hunter_5301 石子合并

本文介绍了一种使用区间动态规划解决的问题:如何合并N堆沙子为一堆,使得合并过程中产生的总代价最小。通过枚举中间点并利用动态转移方程,实现了高效的求解算法。

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

题意

设有NN堆沙子排成一排,其编号为123NN<=300。每堆沙子有一定的数量,可以用一个整数来描述,现在要将这NN堆沙子合并成为一堆,每次只能合并相邻的两堆,合并的代价为这两堆沙子的数量之和,合并后与这两堆沙子相邻的沙子将和新堆相邻,合并时由于选择的顺序不同,合并的总代价也不相同问题是:找出一种合理的方法,使总的代价最小。输出最小代价。

思路

区间动态规划。
f[l][r]为把第ll堆石子和第r堆石子合并到一堆的最小代价。我们枚举一个中间点kk,可以得出动态转移方程:
f[l][r]=minlk<r{f[l][k]+f[k+1][r]}+i=lrAi

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int f[301][301], s[301], a[301], n;
int main() {
    memset(f, 127 / 3, sizeof(f));
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        s[i] = s[i - 1] + a[i];//前缀和快速求出区间和
        f[i][i] = 0;
    }
    for (int l = n - 1; l >= 1; l--) {
        for (int r = l + 1; r <= n; r++)
            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]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值