算法提高 合并石子(DP)
问题描述
在一条直线上有n堆石子,每堆有一定的数量,每次可以将两堆相邻的石子合并,合并后放在两堆的中间位置,合并的费用为两堆石子的总数。求把所有石子合并成一堆的最小花费。
输入格式
输入第一行包含一个整数n,表示石子的堆数。
接下来一行,包含n个整数,按顺序给出每堆石子的大小 。
接下来一行,包含n个整数,按顺序给出每堆石子的大小 。
输出格式
输出一个整数,表示合并的最小花费。
样例输入
5
1 2 3 4 5
1 2 3 4 5
样例输出
33
数据规模和约定
1<=n<=1000, 每堆石子至少1颗,最多10000颗。
#include<stdio.h> #include<stdlib.h> #define INIF 0x3f3f3f3f int N; int dp[1001][1001] = {0}; int sum[1001][1001]; int num[1001]; void minsz() { int i, j, k, t, len, minx; for(i = 1; i <= N; i++) { sum[i][i] = num[i]; for(j = i + 1; j <= N; j++) { sum[i][j] = sum[i][j-1] + num[j];//计算堆到堆的距离 } } for(j = 2; j <= N; j++) { for(i = j-1; i > 0; i--) { minx = INIF; dp[i][j] = INIF; for(k = i; k < j; k++) { t = dp[i][k] + dp[k+1][j] + sum[i][j]; if(t < minx) minx = t; } dp[i][j] = minx; } } printf("%d\n", dp[1][N]); } int main() { int i; scanf("%d", &N); for(i = 1; i <= N; i++) { scanf("%d", &num[i]); } minsz(); return 0; }
永远渴望,大智若愚(stay hungry, stay foolish)