题目链接
https://www.acwing.com/problem/content/284/
思路
闫氏dp分析法,先上图。
状态表示图中已经说的很清楚了,说说状态计算,我们以最后一次合并的两堆的分界线来划分,假定位置为k。那么自然的分界线左边的石子应该是(i,k)右边应该是(k+1,j),然后我们再将所有分法的最后一次划分都去掉,这样相当于所有元素一起减去一个值,不影响求最小值,那么状态转移方程为
f
[
i
]
[
j
]
=
m
i
n
f
[
i
]
[
k
]
+
f
[
k
+
1
]
[
j
]
+
s
[
j
]
−
s
[
i
−
1
]
f [ i ] [ j ] = min{ f [ i ] [ k ] + f [ k + 1 ] [ j ] + s [ j ] - s [ i - 1 ] }
f[i][j]=minf[i][k]+f[k+1][j]+s[j]−s[i−1]。(s数组表达前缀和,求任意一段的和都是这种求法,不知道可以百度一下,不难的。)
时间复杂度为O(n^3)。
代码
#include<bits/stdc++.h>
using namespace std;
int a[305];
int f[305][305];
int n;
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) a[i]+=a[i-1];
for(int len=2;len<=n;len++)
{
for(int i=1;i+len-1<=n;i++)
{
int l=i,r=len+i-1;
f[l][r] = 1e9;
for(int k=l;k<r;k++)
{
f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]+a[r]-a[l-1]);
}
}
}
printf("%d\n",f[1][n]);
return 0;
}