zoukankan      html  css  js  c++  java
  • 【NOI1995】石子合并

    本题在洛谷上的链接:https://www.luogu.org/problemnew/show/P1880


    本来以为是一道简单的区间DP问题,草草地写了个程序结果样例都没过,仔细一看,原来n堆石子摆成了环。区间DP是线性DP的一种,写法比较固定,一般是先枚举区间长度,再枚举区间左端点,推出区间右端点,状态转移通常是枚举中间点。这道题虽然成了环,但本质是不变的,还是从2到n枚举区间长度,只不过区间左端点可以是1到n,区间右端点可以在左端点左侧。为了方便起见,我们可以直接把环变为链跑区间DP,仔细想想,可以把长度为n的环用长度为2*n-1的链来代替。只不过这样,就不能方便的把dp[1][n]作为答案了,而是当区间长度枚举到n时,用每次求出dp值更新答案。详见代码。

     1 #include <cstdio>
     2 #include <algorithm>
     3 
     4 using namespace std;
     5 
     6 const int maxn = 2 * 105, inf = 0x3f3f3f3f;
     7 
     8 int num[maxn], sum[maxn], dp1[maxn][maxn], dp2[maxn][maxn];
     9 
    10 int main() {
    11     int n, ans1 = inf, ans2 = 0;
    12     scanf("%d", &n);
    13     for (int i = 1; i <= n; ++i) scanf("%d", &num[i]);
    14     for (int i = n + 1; i < 2 * n; ++i)
    15         num[i] = num[i - n];
    16     for (int i = 1; i < 2 * n; ++i)
    17         sum[i] = sum[i - 1] + num[i];
    18     for (int l = 2; l <= n; ++l)
    19         for (int i = 1; i <= 2 * n - l; ++i) {
    20             int j = i + l - 1;
    21             dp1[i][j] = inf;
    22             for (int k = i; k < j; ++k) {
    23                 dp1[i][j] = min(dp1[i][j], dp1[i][k] + dp1[k + 1][j] + sum[j] - sum[i - 1]);
    24                 dp2[i][j] = max(dp2[i][j], dp2[i][k] + dp2[k + 1][j] + sum[j] - sum[i - 1]);
    25             }
    26             if (l == n) ans1 = min(ans1, dp1[i][j]), ans2 = max(ans2, dp2[i][j]);
    27         }
    28     printf("%d
    %d", ans1, ans2);
    29     return 0;
    30 }
    AC代码
  • 相关阅读:
    display:block 的认识
    document.dcoumentElement.scrollTop
    display:block的注意
    JavaScript中的Timer是怎么工作的
    创建函数还有一种方法
    $.fn.extend()与$.extend()的使用
    jq遍历的基础语法之二
    损失函数
    Python之函数装饰器
    激活函数
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9602427.html
Copyright © 2011-2022 走看看