专栏文章

题解:P1775 石子合并(弱化版)

P1775题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mioc8xsk
此快照首次捕获于
2025/12/02 16:50
3 个月前
此快照最后确认于
2025/12/02 16:50
3 个月前
查看原文

P1775 石子合并(弱化版)题解

思路

区间动态规划,从小到大 DP 不同的长度的合并最小代价,层层递进,得到长度为 nn 的合并最小代价。
状态转移方程
dp[i][i]=0(1in)dp[i][i]=0 (1 \le i \le n) dp[l][r]=min(dp[l][r],dp[l][mid]+dp[mid+1][r]+sum[r]sum[l1])(1lmid<rn)dp[l][r]= \min (dp[l][r],dp[l][mid]+dp[mid+1][r]+sum[r]-sum[l-1]) (1 \le l \le mid < r \le n)

代码

CPP
#include <bits/stdc++.h>
using namespace std;
//dp[i][j]石子i~j全部合并的最小代价
int dp[310][310],sum[310];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	memset(dp,0x3f,sizeof dp);//在求min之前一定要赋无穷大
	int n;
	cin>>n;
	for (int i=1;i<=n;i++){
		cin>>sum[i];
		sum[i]+=sum[i-1];//前缀和
		dp[i][i]=0;//石子i在合并前没有代价
	}
	//第一层:区间长度
	for (int len=2;len<=n;len++){
		//第二层:左端点
		for (int l=1;l<=n-len+1;l++){
			//右端点=左端点+长度-1
			int r=l+len-1;
			//第三层:左右堆的界限
			//左堆:l~mid,右堆:mid+1~r
			for (int mid=l;mid<r;mid++){
				//每次都要更新最小值
				//dp[l][mid]左堆的最小代价
				//dp[mid+1][r]右堆的最小代价
				//sum[r]-sum[l-1]左右堆的质量和,即这次合并的代价
				dp[l][r]=min(dp[l][r],dp[l][mid]+dp[mid+1][r]+(sum[r]-sum[l-1]));
			}
		}
	}
	cout<<dp[1][n];//区间1~n的合并最小代价
	return 0;
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...