解法:一开始我愚蠢地认为一个一个并就可以了,但是样例都过不去。发现要区间区间地合并才对。那么转移方程就是dp[i][j] = min(dp[i][j], dp[i][k] + dp[k + 1][j] + cnt[j] - cnt[i - 1]);
dp[i][j]表示i到j合并起来的最小花费。cnt[i]是前i个的石子数目。
代码如下:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 210;
const int INF = 0x3f3f3f3f;
int dp[maxn][maxn], a[maxn], cnt[maxn];
int main() {
int n;
while(scanf("%d", &n) != EOF) {
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
cnt[i] = cnt[i - 1] + a[i];
}
for(int k = 2; k <= n; k++) {
for(int i = 1; i <= n - k + 1; i++) {
int j = i + k - 1;
dp[i][j] = INF;
for(int l = i; l < j; l++) {
dp[i][j] = min(dp[i][j], dp[i][l] + dp[l + 1][j] + cnt[j] - cnt[i - 1]);
}
}
}
printf("%d\n", dp[1][n]);
}
return 0;
}