AcWing 282. 石子合并
原题链接
简单
作者:
jc_9
,
2021-03-22 01:18:04
,
所有人可见
,
阅读 320
/*
f[l,r]表示把l到r合并成一堆的最小代价
1.先把区间[l,r]切分为两部分,[l,k]和[k+1,r],k是切分点
2.再把两部分[l,k]和[k+1,r]合并在一起,用前缀和来求区间和
3转移方程:f[l,k] + f[k+1,r] + s[r] - s[l-1] -> f[l,r]
4.计算f[l,r] = min(f[l,r],f[l,k] + f[k+1,r]+s[r] - s[l-1])
5.初值 f[i,i] = 0(合并自己的代价为0),其余为正无穷,便于求最小值
6.目标:f[1,n];
*/
#include<iostream>
using namespace std;
const int N = 310;
#include<cstring>
int n;//石子堆数量
int a[N];//记录每堆石子的指令
int s[N];//记录前缀和
int f[N][N];//f[l][r]表示把l到r合并成一堆的最小代价
int main()
{
//预处理
memset(f,0x3f,sizeof(f));
cin >> n;
for(int i =1;i<=n;i++)
{
cin >>a[i];//每堆石子的质量
s[i] = s[i-1] + a[i];//前缀和
f[i][i] = 0;
}
//状态计算
for(int len = 2;len<=n;len++)//阶段,枚举区间长度
for(int l =1;l+len-1<=n;l++)//状态:枚举区间起点
{
int r = l + len -1;//区间终点
for(int k = l;k<r;k++)
{
f[l][r] = min(f[l][r],f[l][k] + f[k+1][r] + s[r] - s[l-1]);
}
}
cout << f[1][n] << endl;
}