zoukankan      html  css  js  c++  java
  • 区间 dp

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

      有 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;
    }
    
    东北日出西边雨 道是无情却有情
  • 相关阅读:
    Spring-Cloud 学习笔记-(4)负载均衡器Ribbon
    Spring-Cloud 学习笔记-(5)熔断器Hystrix
    微信支付(APP)
    Resetting Frame Animation
    Java内部类与final关键字详解
    UML中关联(Association)和依赖(Dependency)的区别
    ListView 介绍
    android Activity类中的finish()、onDestory()和System.exit(0) 三者的区别
    AsyncTask和Handler对比
    create groups 和 create folder reference
  • 原文地址:https://www.cnblogs.com/ccut-ry/p/7494164.html
Copyright © 2011-2022 走看看