以一个经典题目引入到正题 :
有 n 堆石子 , 每两堆石子合并会花费一定的价值,所花费的价值即为 两堆石子上的价值和 , 问合并所有的石子后的最小花费 ?
思路分析 :
因为题干可以看成是对每个区间的 的操作,找到问题的子问题 , 即只有一堆石子, 即区间长度为 1 的情况 ,它并不要合并 , 所以花费的代价为 0 ,当有两堆石子时 , 区间长度为 2 , 此时所花费的代价为 为两堆的和 , 当区间长度为 3 时 ,此时分割区间 , 会分成 1 个长度为 1 的区间 和一个长度为 2 的区间 , 长度为 2 的区间所花费的代价在前面已经计算过 , 并且也已经是最优的解 。
代码示例 :
int sum[500]; int dp[230][230]; int main() { int n, x; while ( ~scanf("%d", &n)){ memset(sum, 0, sizeof(sum)); for(int i = 1; i <= n; i++){ scanf("%d", &x); sum[i] = sum[i-1] + x; } memset(dp, 0, sizeof(dp)); for(int l = 2; l <= n; l++) { // l 表示区间的长度 for(int i = 1; i <= n; i++){ // i 表示区间的始端 int j = l + i - 1; // j 表示区间的尾端 if (j > n) break; // 此判断条件很重要 , 可以优化很多 , 当区间尾超过整个区间长度时 , 即结束此层 for dp[i][j] = 0x3f3f3f3f; for(int k = i; k < j; k++){ dp[i][j] = min(dp[i][j], dp[i][k]+dp[k+1][j]+sum[j]-sum[i-1]); // 对于每一刀切开的区间 , 最终合并起来的区间还要加上整段区间合并的花费 } } } printf("%d ", dp[1][n]); } return 0; }