码迷,mamicode.com
首页 > 其他好文 > 详细

区间 dp

时间:2017-09-08 14:47:29      阅读:145      评论:0      收藏:0      [点我收藏+]

标签:pre   min   return   问题   highlight   条件   情况   代码示例   div   

 

以一个经典题目引入到正题 :

  有 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\n", dp[1][n]);
    }

    return 0;
}

 

区间 dp

标签:pre   min   return   问题   highlight   条件   情况   代码示例   div   

原文地址:http://www.cnblogs.com/ccut-ry/p/7494164.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!