51Nod - 1021 石子归并
第1行:N(2 <= N <= 100) 第2 - N + 1:N堆石子的数量(1 <= A[i] <= 10000)
输出最小合并代价
4 1 2 3 4
19
题解:
使用dp动态规划, dp[i][j] 表示的是从 第 i 到 第j个元素的合并最小和。 sum[i][j] 是第i到第j的累积和。 (包含第 i, j两个断点)
有公式 dp[i][j] = min( dp[i][j], dp[i][k] + dp[k+1][j] + sum[i][j] );
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAXN = 102;
int n, num[MAXN], dp[MAXN][MAXN], sum[MAXN][MAXN];
int main(){
while(scanf("%d", &n) != EOF){
for(int i=1; i<=n; ++i){
scanf("%d", &num[i]);
}
memset(sum, 0, sizeof(sum));
for(int i=1; i<=n; ++i){
for(int j=i; j<=n; ++j){
sum[i][j] = sum[i][j-1] + num[j];
}
}
memset(dp, 0x3f3f3f3f, sizeof(dp));
for(int i=0; i<=n; ++i){
for(int j=0; j<=n; ++j){
if(i >= j){
dp[i][j] = 0;
}
}
}
for(int i=1; i<=n; ++i){
for(int j=i-1; j>=1; --j){
for(int k=j; k<i; ++k){
dp[j][i] = min(dp[j][i], dp[j][k] + dp[k+1][i] + sum[j][i] );
}
}
}
printf("%d\n", dp[1][n] );
}
return 0;
}
原文:http://www.cnblogs.com/zhang-yd/p/6858494.html