石子合并(弱化版)

洛谷题面

题目大意

设有 N(N300) 堆石子排成一排,其编号为 1,2,3,,N。每堆石子有一定的质量 mi(mi1000)

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

试找出一种合理的方法,使总的代价最小,并输出最小代价。

题目分析

辨别区间 DP 的方式:

从小区间延伸到大区间(合并等方式)。

许多括号数数题就是区间 DP 好题,今年 2021-CSP-S-括号序列 不妨一做。


dp[l][r] 表示区间 [l,r] 内合并的最小代价。

枚举左右区间,再枚举中间断点来判断是否答案会变得更优:

dp[l][r]=min{dp[l][k]+dp[k+1][r]+cost}(lk<r)

其中 cost 表示 i=lrai

枚举区间(左右+断点)复杂度为 O(N3),中间枚举价值的部分又是 O(N),总时间复杂度 O(N4)

枚举价值部分可以通过前缀和优化,优化为 O(N3)

代码

//2022/1/6

const int INF=0x3f3f3f3f;

const int ma=305;

int a[ma],sum[ma];

int dp[ma][ma];

int n;

int main(void)
{
	n=read();
	
	Input_Int(n,a);
	
	for(register int i=1;i<=n;i++)
	{
		sum[i]=sum[i-1]+a[i];
	}
	
	for(register int len=2;len<=n;len++)
	{
		for(register int l=1;l+len-1<=n;l++)
		{
			int r=l+len-1;
			
			dp[l][r]=INF;
			
			for(register int k=l;k<r;k++)
			{
				int w=sum[r]-sum[l-1];
				
				dp[l][r]=min(dp[l][r],dp[l][k]+dp[k+1][r]+w);
			}
		}
	}
	
	printf("%d\n",dp[1][n]);
	
	return 0;
}

本文作者:Coros_Trusds

本文链接:https://www.cnblogs.com/Coros-Trusds/p/15773115.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Coros_Trusds  阅读(306)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
🔑
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.