【P1880】 [NOI1995]石子合并 {区间DP}

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define repo(i,a,b) for(register int i=(a);i<=(b);++i)
#define repi(i,a,b) for(register int i=(a);i>=(b);++i)
using namespace std;

int n;
int ans1 = 0x3f3f3f3f,ans2 = -1;
int a[210],sum[210],f1[210][210],f2[210][210];

inline int read(){
    int s=0,w=1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){if(ch == '-')w = -1;ch = getchar();}
    while(ch >= '0' && ch <= '9'){s = s*10+ch-'0';ch = getchar();}
    return s*w;
}

void dp(){
    memset(f1,0x3f3f3f3f,sizeof(f1));
    repo(i,1,2*n){
        f1[i][i] = 0;
    }
    repo(len,2,n){
        repo(i,1,2*n-len+1){
            repo(k,i,i+len-2){
                f1[i][i+len-1] = min(f1[i][i+len-1],f1[i][k]+f1[k+1][i+len-1]+sum[i+len-1]-sum[i-1]);
                f2[i][i+len-1] = max(f2[i][i+len-1],f2[i][k]+f2[k+1][i+len-1]+sum[i+len-1]-sum[i-1]);
            }
        }
    }
}

int main(){
    n = read();
    repo(i,1,n){
        a[i] = read();
        a[i+n] = a[i];
        sum[i] = a[i]+sum[i-1];
    }
    repo(i,n+1,2*n){
        sum[i] = sum[i-1]+a[i];
    }

    dp();

    repo(i,1,n){
        ans1 = min(f1[i][i+n-1],ans1);
        ans2 = max(f2[i][i+n-1],ans2);
    }

    printf("%d
%d",ans1,ans2);
    return 0;
}
原文地址:https://www.cnblogs.com/c-come/p/10293765.html