• 「区间DP」[NOI1995]石子合并


    [NOI1995]石子合并

    原题链接:[NOI1995]石子合并

    题目大意

    给你(n)堆石子,现在要相邻两堆合成一堆,直到所有石子都在一堆里面为止,然后 1 号位的石子可以和 (n) 号位的石子合并,也就是说,这些石子堆围成了一个环。

    每次合并有一个分数,这个分数就是新合并的石子堆的石子数,求最终的最小得分和最大得分

    题目题解

    第一次写区间DP,蛮好,区间DP相比于其他的DP至少有一个固定的模板和思维方向,也就是常说的挺套路的,看了下题解就明白了了

    转移方程

    (f_{i, j} = f_{i, k} + f_{k + 1, j} + d(i, j)) (d)为合并的分数

    因为要满足DP的无后效性且一定要由已知推未知,于是区间dp也有一些改动,详细看代码

    //#define fre yes
    
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    
    const int N = 305;
    int arr[N];
    int f1[N][N], f2[N][N];
    int s[N];
    
    int main() {
        static int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &arr[i]);
            arr[n + i] = arr[i];
        }
    
        for (int i = 1; i <= n * 2; i++) {
            s[i] = s[i - 1] + arr[i];
        }
    
        for (int p = 1; p < n; p++) {
            for (int i = 1, j = i + p; j <= 2 * n && i <= 2 * n; i++, j++) {
                f2[i][j] = 1e9;
                for (int k = i; k < j; k++) {
                    f1[i][j] = std::max(f1[i][j], f1[i][k] + f1[k + 1][j] + s[j] - s[i - 1]);
                    f2[i][j] = std::min(f2[i][j], f2[i][k] + f2[k + 1][j] + s[j] - s[i - 1]);
                }
            }
        }
    
        int minn = 1e9, maxx = 0;
        for (int i = 1; i <= n; i++) {
            maxx = std::max(maxx, f1[i][i + n - 1]);
            minn = std::min(minn, f2[i][i + n - 1]);
        } printf("%d
    %d", minn, maxx);
    }
    
    
  • 相关阅读:
    PHP-FPM 重启
    white-space: nowrap
    php-fpm 优化
    & 引用传值
    tp3 save操作小bug误区
    用百度接口验证是否上传了身份证图片信息[非姓名,身份证号匹配]
    nginx 反向代理案例
    IOS把图片缓存到本地的几种方法
    ios沙盒查找图片展示
    iOS模拟器沙盒使用推荐
  • 原文地址:https://www.cnblogs.com/Nicoppa/p/11505932.html
Copyright © 2020-2023  润新知