石子合并(一排石头哦)区间dp入门

该博客介绍了一个关于石子合并的问题,要求通过区间动态规划(DP)找到合并石子的最优策略,目标是使合并过程中的得分总和最小和最大。问题规模为n堆石子,每堆石子数不超过200,需要实现从n-1次合并中找到最有利的合并方案。博客中提供了问题分析和代码实现。
摘要由CSDN通过智能技术生成

石子合并(一排石头)

题目描述
有N堆石子排成一排(n<=100),现要将石子有次序地合并成一堆,规定每次只能选相邻的两堆合并成一堆,并将新的一堆的石子数,记为改次合并的得分,编一程序,由文件读入堆数n及每堆石子数(<=200);
(1)选择一种合并石子的方案,使得做n-1次合并,得分的总和最少
(2)选择一种合并石子的方案,使得做n-1次合并,得分的总和最多
输入
第一行为石子堆数n
第二行为每堆石子数,每两个数之间用一空格分隔。
输出
从第1至第n行为得分最小合并方案,第n+1行为空行,从n+2到2n+1行是得分最大的合并方案。

样例输入

4
4 5 9 4

样例输出

44
54

分析样例:
最小:

9 9 4分数为9(合并459 13分数为13(合并4922 分数为22(合并913)
总分数等于9+13+22=44

最大

4 14 4分数为14(合并954 18分数为18(合并41422分数为22(合并418)
总分数等于14+18+22=54

我们用 l e n len len模拟长度, i i i模拟结束点, j j j模拟起点, e n d end end为结束点
最小值为 f n [ j ] [ e n d ] = m i n ( f n [ j ] [ e n d ] , f n [ j ] [ i ] + f n [ i + 1 ] [ e n d ] + s u m [ e n d ] − s u m [ j − 1 ] ) ; fn[j][end]=min(fn[j][end],fn[j][i]+fn[i+1][end]+sum[end]-sum[j-1]); fn[j][end]=min(fn[j][end],fn[j][i]+fn[i+1][end]+sum[end]sum[j1]);
最大值为 f x [ j ] [ e n d ] = m a x ( f x [ j ] [ e n d ] , f x [ j ] [ i ] + f x [ i + 1 ] [ e n d ] + s u m [ e n d ] − s u m [ j − 1 ] ) ; fx[j][end]=max(fx[j][end],fx[j][i]+fx[i+1][end]+sum[end]-sum[j-1]); fx[j][end]=max(fx[j][end],fx[j][i]+fx[i+1][end]+sum[end]sum[j1]);
上代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f
using namespace std;
int stone[105],n,fn[205][205],fx[205][205],sum[205];
int main() {
    cin>>n;
    memset(sum,0,sizeof(sum));
    memset(fn,INF,sizeof(fn));
    memset(fx,-1,sizeof(fx));
    for(int  i=1; i<=n; i++) {
        cin>>stone[i];
        sum[i]=sum[i-1]+stone[i];//数组预处理
        fn[i][i]=0;//数组预处理
        fx[i][i]=0;//数组预处理
    }
    for(int len=1; len<=n; len++)//长度模拟
        for(int j=1; j+len<=n+1; j++) {//起点模拟
            int end=j+len-1;//结束点
            for(int i=j; i<end; i++)//结束点模拟
                fn[j][end]=min(fn[j][end],fn[j][i]+fn[i+1][end]+sum[end]-sum[j-1]),
                fx[j][end]=max(fx[j][end],fx[j][i]+fx[i+1][end]+sum[end]-sum[j-1]);
        }
    cout<<fn[1][n]<<endl<<fx[1][n]<<endl; 
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值