zoukankan      html  css  js  c++  java
  • P1880 [NOI1995]石子合并

    P1880 [NOI1995]石子合并

    做过类似的,不过这题稍微有点不一样:是环不是链。

    只要把链复制一遍原来的链的后面,就可以化环为链了。

    注意题目求的是N堆石子合并,枚举区间长度的时候依然是从2枚举到N。

    int a[maxn];
    int b[maxn];
    //前缀和
    int dp1[maxn][maxn], dp2[maxn][maxn];
    
    int main()
    {
        int N; cin >> N;
        memset(dp1, INF, sizeof(dp1));
        memset(dp2, -INF, sizeof(dp2));
        for (int i = 1; i <= N; i++) {
            dp1[i][i] = dp2[i][i] = dp1[N + i][N + i] = dp2[N + i][N + i] = 0;
        }
       //自己和自己合并得分为0
        for (int i = 1; i <= N; i++) {
            cin >> a[i];
            a[i + N] = a[i];
        }
      //化环为链
        for (int i = 1; i <= N + N - 1; i++) {
            b[i] = b[i - 1] + a[i];
        }
    
        for (int len = 2; len <= N; len++) {
            //枚举长度
            for (int l = 1; l <= N+N - len + 1; l++) {
                //枚举左端点l
                int r = l + len - 1;
                for (int spl = l; spl <= r - 1; spl++) {
                    //枚举分割点split
                    //表示在spl堆与spl+1堆之间分割
                    dp1[l][r] = min(dp1[l][r], dp1[l][spl] + dp1[spl + 1][r]);
                    dp2[l][r] = max(dp2[l][r], dp2[l][spl] + dp2[spl + 1][r]);
                }
                dp1[l][r] += b[r] - b[l - 1];
                dp2[l][r] += b[r] - b[l - 1];
            }
        }
        //长度为N的区间全扫一遍取最大/最小值
        int mmax = -1;
        int mmin = INF;
        for (int i = 1; i <= N; i++) {
            mmin = min(mmin, dp1[i][i + N - 1]);
            mmax = max(mmax, dp2[i][i + N - 1]);
        }
        cout << mmin << endl << mmax << endl;
        return 0;
    }
    
  • 相关阅读:
    工厂模式
    将博客搬至CSDN
    网络安全-跨站脚本攻击XSS(Cross-Site Scripting)
    Linux 权限
    git常用的语句
    git代码提交与克隆
    git学习
    Mybatis常见问题
    关于集合常见的问题
    远程连接(加密验证问题解决)
  • 原文地址:https://www.cnblogs.com/streamazure/p/13693971.html
Copyright © 2011-2022 走看看