首页 > 其他分享 >区间PD之石子合并

区间PD之石子合并

时间:2023-06-07 23:01:00浏览次数:66  
标签:11 int 石子 合并 枚举 PD 代价

设有 N堆石子排成一排,其编号为 1,2,3,…,N

每堆石子有一定的质量,可以用一个整数来描述,现在要将这 N堆石子合并成为一堆。

每次只能合并相邻的两堆,合并的代价为这两堆石子的质量之和,合并后与这两堆石子相邻的石子将和新堆相邻,合并时由于选择的顺序不同,合并的总代价也不相同。

例如有 4 堆石子分别为 1 3 5 2, 我们可以先合并 1、2 堆,代价为 4,得到 4 5 2, 又合并 1、2 堆,代价为 9,得到 9 2 ,再合并得到 11,总代价为 4+9+11=24;

如果第二步是先合并 2、3堆,则代价为 7,得到 4 7,最后一次合并代价为 11,总代价为 4+7+11=22

问题是:找出一种合理的方法,使总的代价最小,输出最小代价。

输入格式

第一行一个数 N表示石子的堆数 N。

第二行 N 个数,表示每堆石子的质量(均不超过 1000)。

输出格式

输出一个整数,表示最小代价。

数据范围

1≤N≤300

输入样例:

4
1 3 5 2

输出样例:

22


模拟一下最基本的过程。

我们假设f[i][j]为将石子从 i - j 合并的最小代价。

如果以1-n这n个数中的间隔划分

f[i][j] = min(f[1][k]+f[k+1[n]+s[n])  k 属于1~n   s[n]是1~n这n个数的和,即最后一次合并的花费。

然后f[1][k] 和 f[k+1][n]又可以通过同样的分法得出

这就满足了DP最基本的思想,小状态求解大状态。


状态转移方程:

f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[j-1]);



代码:

#include<iostream>
using namespace std;
const int N=310;

int a[N],s[N],f[N][N];
int n;

int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    for(int i=1;i<=n;i++)s[i]=s[i-1]+a[i];//求前缀和
   for(int len = 2;len<=n;len++)//枚举区间长度
  	for(int i=1;i+len-1<=n;i++)//枚举左边界
  	{  
      	int j = i+len-1;
     	  f[i][j]= 0x3f3f3f3f;
      	for(int k=i;k<=j;k++)//枚举划分点
      	{
          f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+s[j]-s[i-1]);
      	}
 		 } 
    cout<<f[1][n];
}


当然有人可能还会想到另一种枚举方法

枚举左边界

枚举有边界

然后再枚举划分点

但是这样写会出现一个问题,就是在枚举划分点的时候,我们划分点左边的那一段,可能求出来了,但是划分点的另一段,起点未被枚举到,所以就没算出来过。

例:

for(int i=1;i<=n;i++)f[i][i]=a[i];
for(int i=1;i<=n;i++)f[i][i]=a[i];
    for(int i=1;i<=n;i++)//枚举左边界
    {
        for(int j=1;j<=n;j++)//枚举右边界
        {
            if(i!=j)
            {
                f[i][j]=0x3f3f3f3f;
                for(int k=i;k<j;k++)//枚举划分段
                {
                    f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]);//这样划分就会碰到一个非常尴尬的情况
                    //就是说我i还是1的时候我f[k+1][j]中的k+1显然还没计算过。
                }
            }
        }
    }













标签:11,int,石子,合并,枚举,PD,代价
From: https://blog.51cto.com/u_15784515/6436246

相关文章

  • Xshell/Xftp/Xlpd Plus 7:官方免破全功能无限制版(2023更新)
    XshellPlus7是一款集成了Xshell7(SSH客户端)和Xftp7(SFTP客户端)的软件套餐,可以让您在访问远程终端的同时,进行多窗口的文件传输和编辑,大大提高您的工作效率。XshellPlus7支持多种协议,如SSH,SFTP,TELNET,RLOGIN,SERIAL等,还具有强大的安全性和可定制性。本文将为您详细介绍XshellPlus......
  • vue 预览word文档、图片、pdf文件等
    <el-buttonsize="mini"type="text"icon="el-icon-edit"@click="handlePreviewFile(obj)">预览</el-button><el-dialogtitle="预览":visible.sync="......
  • Linq关联两个DataTable合并为一个DataTable
    DataSetds;DataTabledt1=ds.Tables[0];DataTabledt2=ds.Tables[1];//关联varres=frommindt1.AsEnumerable()fromsindt2.AsEnumerable()wherem.Field&l......
  • 题解 P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并
    传送门如题目所言,这就是个线段树合并的板子题。题目大意题目描述首先村落里的一共有\(n\)座房屋,并形成一个树状结构。然后救济粮分\(m\)次发放,每次选择两个房屋\((x,y)\),然后对于\(x\)到\(y\)的路径上(含\(x\)和\(y\))每座房子里发放一袋\(z\)类型的救济粮。然......
  • Luogu P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并
    [Vani有约会]雨天的尾巴/【模板】线段树合并题目背景深绘里一直很讨厌雨天。灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切。虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地里的粮食被弄得一片狼藉。无奈......
  • 转载:PageOffice动态生成Word文件并转换为PDF
    说明:PageOffice是客户端插件,做不到纯后台调用把word转为pdf。但是pageoffice的FileMaker对象可以实现不在客户端打开文件直接转换文件为pdf并保存到服务器端,看起来跟服务器端转换的效果一样。1、环境前端:vue后端:springboot、pageoffice5.4.0.3版本2、前端在index.vue页面定......
  • 使用ffmpeg合并两个音频文件
    #寻找指定路径下所有的wav文件find$filePath-iname"*.wav">wav.flist#依次取出每个wav文件,与test.wav进行合并forlinein`catwav.flist`doecho$lineffmpeg-ipath/to/test.wav-i$line-filter_complex"[0:a]volume=1,atrim=1:4[a1];[1:a]volume=0.5[a......
  • mysql数据库的锁-select for update
    乐观锁与悲观锁乐观锁和悲观锁只是两个加锁的思路,其实现方式多种多样。以下举几个在mysql数据库中的例子。  对于一次的数据修改,我们可以大概将其分为三步:获取数据修改数据提交修改乐观锁假设A、B两个角色对数据进行修改:乐观锁对数据保持一个乐观态度(大概率......
  • 合并数组与非合并数组 -- SystemVerilog
    合并型数组(packed):合并型数组可以实现连续的存储,赋值时不需要用 ’{}。 数组中,数据排列为{ b_pack[2], b_pack[1],b_pack[0]},其中每个b_pack为8个bit;bit是二值逻辑,每位bit只占据1位。故24位(8bit*3)只占据一个word(一般一个word为32bit)的存储空间。 非合并型数组......
  • 全网最详细的 tcpdump 使用指南
    https://www.cnblogs.com/wongbingming/p/13212306.html 今天要给大家介绍的一个Unix下的一个 网络数据采集分析工具,也就是我们常说的抓包工具。与它功能类似的工具有wireshark,不同的是,wireshark有图形化界面,而tcpdump则只有命令行。由于我本人更习惯使用命令行的方......