区间 dp

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了区间 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\n", dp[1][n]);
    }

    return 0;
}

 

以上是关于区间 dp的主要内容,如果未能解决你的问题,请参考以下文章

HDU 5115 Dire Wolf ——(区间DP)

HDU 5115 Dire Wolf(区间dp)

区间DP小结(附经典例题) 转载

poj2955 区间dp

BZOJ1260 [CQOI2007]涂色paint(区间dp)

括号匹配问题(区间dp)