1. 程式人生 > 實用技巧 >[NOI1995]石子合併 - 洛谷P1880

[NOI1995]石子合併 - 洛谷P1880

題目

https://www.luogu.com.cn/problem/P1880

CODE

區間DP
環 -> 鏈
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <stack>
#include <set>
using namespace std;

int n, a[101], sum[201], dps[201][201], dpb[201][201];

int main(){
    scanf("%d", &n);
    memset(dps, 0x3f3f3f, sizeof(dps));
    memset(dpb, -1, sizeof(dpb));
    for(int i = 1; i <= n; i++){
        scanf("%d", &a[i]);
        dps[i][i] = 0;
        dpb[i][i] = 0;
        sum[i] = sum[i - 1] + a[i];
    }
    for(int i = 1; i <= n; i++){
        dps[i + n][i + n] = 0;
        dpb[i + n][i + n] = 0;
        sum[i + n] = sum[i + n - 1] + a[i];
    }
    for(int len = 1; len <= n; len++){
        for(int i = 1; i + len <= 2 * n; i++){
            int ends = i + len - 1;
            for(int j = i; j <= ends-1; j++){
                dps[i][ends] = min(dps[i][ends], dps[i][j] + dps[j+1][ends] + sum[ends] - sum[i - 1]);
                dpb[i][ends] = max(dpb[i][ends], dpb[i][j] + dpb[j+1][ends] + sum[ends] - sum[i - 1]);
            }
        }
    }
    int minn = 1e9+10, maxn = -1;
    for(int i = 1; i <= n; i++){
        minn = min(dps[i][n+i-1], minn);
        maxn = max(dpb[i][n+i-1], maxn);
    }
    printf("%d\n%d\n", minn, maxn);
    return 0;
}