区间DP-石子合并 (环形)

本文介绍了如何解决将石子在环形操场上合并成一堆的算法问题,通过动态规划方法,计算合并过程中的最小得分和最大得分。文章详细解析了两种不同的DP格式,包括分割区间进行合并的策略,并提供了输入输出样例。
摘要由CSDN通过智能技术生成

7-10 石子合并

在一个圆形操场的四周摆放 N 堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的 2 堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分。

试设计出一个算法,计算出将 N 堆石子合并成 1 堆的最小得分和最大得分。

输入格式:

数据的第 1 行是正整数 N ,表示有 N 堆石子。

第 2 行有 N 个整数,第 i 个整数 ai 表示第 i 堆石子的个数。

输出格式:

输出共 2 行,第 1 行为最小得分,第 2 行为最大得分。

输入样例:

4
4 5 9 4

输出样例:

43
54

思路:分两种解法
第一种DP格式为(dp[i][j]=min(dp[i][j],dp[i][k]+dp[i+k][j-k]+sth))
dp[i][j]为从位置i开始,累加j堆石子的结果
k将区间分割为左右,左区间累加k堆,右区间累加j-k堆,先分别在两个区间合并即得出dp[i][k]与dp[i+k][j-k],再合并区间加上本次合并产生的值即sth
(比较直接合并和k分割合并那个值是我们要的)

PS:本题解中采用将环形拓展成2倍链状,以数组存储前缀和的方式利用差值进行区间内堆累加的计算,也可采用mod的方式实现环形DP

#include<bits/stdc++.h>
using namespace std;
int n;
int a[510],sum[510];
//sum[i]以前缀和形式,记录前i堆石子和 
int dp_min[510][510],dp_max[510][510];
//dp[i][j]为从位置i开始,累加j堆石子的结果 
int main()
{
   
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
   
    	scanf("%d",&a[i]);
        sum[i]=sum[i-1]+a[i];
        dp_min[i][1]=dp_max[i][1]=0;
        //每个位置只合成自己是0 
    }
    for(int i=n+1;i
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值