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

区间DP学习 LibreOJ-10147 石子合并

时间:2020-08-01 21:36:53      阅读:101      评论:0      收藏:0      [点我收藏+]

标签:说明   inline   turn   for   区间dp   循环   lib   顺序   一次循环   

区间DP是线性DP的一种,它以“区间长度”作为DP的“阶段”,使两个坐标(区间的左右端点)描述每个维度。

区间DP中,一个状态由若干个比它更小且包含于它的区间所代表的状态转移而来。区间DP的初态一般就由长度为1的“元区间”组成。这种向下划分,再向上递推的模式与某些树形结构如线段树有很大的相似之处。

 

石子合并

若第l堆和第r堆被合并,说明l-r之间的每堆石子都已经合并,这样l,r才可能相邻。因此任意一堆石子均可以用一个闭区间[l , r] 来描述。

动态规划中,就意味着两个长度较小的区间上的信息向一个更长的区间发生了转移,划分点k就是转移的决策点。 因此把区间长度len作为DP的阶段。

编程实现动态规划状体转移方程时,务必分清 阶段 , 状态与决策,三者应该从外到内的顺序一次循环。

int s[205];
int f1[205][205];
int f2[205][205];
int num[305];
int n;

inline int d(int i, int j) {
    return s[j] - s[i - 1];
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n + n; i++) {
        if(i <= n) scanf("%d", &num[i]);
        num[i + n] = num[i];
        s[i] = s[i - 1] + num[i];
    }
    for (int p = 1; p < n; p++) {
        for (int i = 1, j = i + p; (j < n + n) && (i < n + n);i++, j = i + p) {
            f2[i][j] = INF;
            for (int k = i; k < j; k++) {
                f1[i][j] = max(f1[i][j], f1[i][k] + f1[k + 1][j] + d(i, j));
                f2[i][j] = min(f2[i][j], f2[i][k] + f2[k + 1][j] + d(i, j));
            }
        }
    }
    int Max = -1;
    int Min = INF;
    for (int i = 1; i <= n; i++) {
        Max = max(Max, f1[i][i + n - 1]);
        Min = min(Min, f2[i][i + n - 1]);
    }
    printf("%d\n%d", Min, Max);
}

 

区间DP学习 LibreOJ-10147 石子合并

标签:说明   inline   turn   for   区间dp   循环   lib   顺序   一次循环   

原文地址:https://www.cnblogs.com/hznumqf/p/13416322.html

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