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

    参考的大佬的博客

    求什么设什么,dp[l][r]为l到r堆范围的石子数量的最值

    相邻合并为一堆,所以枚举最小值是2

    这两堆又是由另外的两堆石子合并,可认为是由dp[l][k]和dp[k + 1][r]

    根据k的值将对应范围分为了两部分,然后根据公式会分为更多部分

    #include <bits/stdc++.h>
    using namespace std;
    int n,a[210];
    int dp1[210][210],dp2[210][210];
    int main(){
        //freopen("in","r",stdin);
        ios::sync_with_stdio(0);
        cin >> n;
        for(int i = 1; i <= n; i++){
            cin >> a[i];
            a[i + n] = a[i];
        }
    
        for(int i = 1; i <= 2 * n; i++)
            a[i] += a[i - 1];
    
        //枚举区间长度,最小是2堆开始合并
        for(int len = 2; len <= n; len++){
            //枚举起点
            for(int l = 1; l + len - 1 <  2 * n; l++){
                int r = l + len - 1;//终点
                dp1[l][r] = 99999;
                dp2[l][r] = -99999;
                //不能等于,等于的话就是一堆了
                for(int k = l; k < r; k++){
                    dp1[l][r] = min(dp1[l][r],dp1[l][k] + dp1[k + 1][r] + a[r] - a[l - 1]);
                    dp2[l][r] = max(dp2[l][r],dp2[l][k] + dp2[k + 1][r] + a[r] - a[l - 1]);
                }
            }
        }
        int minn = 99999;
        int maxx = -99999;
        for(int i = 1; i <= n; i++){
            minn = min(minn,dp1[i][i + n - 1]);
            maxx = max(maxx,dp2[i][i + n - 1]);
        }
        cout << minn << endl << maxx;
        return 0;
    }
    View Code
  • 相关阅读:
    CF1172F
    CF506E
    【清华集训2014】玛里苟斯
    CF516E Drazil and His Happy Friends
    [NOI2017]游戏(2-SAT)
    [bzoj2878][Noi2012]迷失游乐园(基环树dp)
    bzoj3545/bzoj3551 [ONTAK2010]Peaks/Peaks加强版
    [bzoj1791][ioi2008]Island 岛屿(基环树、树的直径)
    [AT2306]Rearranging(拓扑序)
    [bzoj5301][Cqoi2018]异或序列
  • 原文地址:https://www.cnblogs.com/xcfxcf/p/12797322.html
Copyright © 2011-2022 走看看