19182 石子合并(基础版)

Description

设有 N(N≤300) 堆石子排成一排,其编号为1,2,3,⋯,N。每堆石子有一定的质量 mi(mi≤1000)。
现在要将这N堆石子合并成为一堆。每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和,合并后与这两堆石子相邻的石子将和新堆相邻。
合并时由于选择的顺序不同,合并的总代价也不相同。试找出一种合理的方法,使总的代价最小,并输出最小代价。

输入格式

第一行,一个整数 N。

第二行,N 个整数 mi。

输出格式

输出仅一个整数,也就是最小代价。(题目确保答案在int范围)

输入样例

4
2 5 3 1

输出样例

22

解析:重点在于设置分割点,代表了不同的合并决策,大小为l<k<r。起点l总是从1开始,r为l+枚举区间长度-1.最后输出f[1][n].

#include <iostream>
#include <cstring>
#include <math.h>
#include <algorithm>
using namespace std;

const int N=100;
int a[N];//每个石子的重量
int s[N];石子重量前缀和
int f[N][N];合并代价

int main()
{
    int n;
    cin>>n;
    memset(f,0x3f,sizeof(f));
    for(int i=1;i<=n;i++){
        cin>>a[i];
        s[i]=s[i-1]+a[i];
        f[i][i]=0;
    }
    int len=0;
    //区间动态规划
    //将区间划分为大小为len的枚举区间长度
    for(len=2;len<=n;len++){
        //设置起点
        for(int l=1;l+len-1<=n;l++){
            //设置终点
            int r=l+len-1;
            //在区间内设置分割点,方便进行动态代价计算
            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]);
            }
        }

    }
    cout << f[1][n] << endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值