题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1021
题意:中文题诶~
思路:区间dp
我们用num[i]存储前i个元素的和,用dp[i][j]存储合并从第i个到第j个元素的代价,那么有动态转移方程式为:
dp[i][j]=min(dp[i][j], dp[i][k]+dp[k+1][j]+num[j]-num[i-1]);
还有一个问题:如果我们直接枚举i, j的话有可能我们在计算dp[i][j]时dp[k+1][j]还没计算出来,这样我们自然不能得到正确答案咯.
其实我们只要换个思路就能解决这个问题啦,我们枚举len, 和i,len表示当前合并的区间长度为len,那么j=i+len-1.
这样就不会有上面的问题啦,因为区间i,k和区间k+1,j的长度一定小于区间i, j的长度,即在计算dp[i][j]之前我们已经计算出dp[i][k]和dp[k+1][j]啦.
代码:
1 #include <bits/stdc++.h>
2 #define MAXN 110
3 using namespace std;
4
5 int a[MAXN], num[MAXN], dp[MAXN][MAXN]; //***dp[i][j]存储第i堆到第j堆的合并代价
6 const int inf=0x3f3f3f3f;
7
8 int main(void){
9 int n, ans=0;
10 cin >> n;
11 for(int i=1; i<=n; i++){
12 cin >> a[i];
13 num[i]=num[i-1]+a[i];
14 }
15 for(int len=2; len<=n; len++){
16 for(int i=1; i<n; i++){
17 int j=i+len-1; //***这里要注意j可能会大于n
18 if(j<=n){
19 dp[i][j]=inf;
20 for(int k=i; k<j; k++){
21 dp[i][j]=min(dp[i][j], dp[i][k]+dp[k+1][j]+num[j]-num[i-1]);
22 }
23 }
24 }
25 }
26 cout << dp[1][n] << endl;
27 }