0
点赞
收藏
分享

微信扫一扫

P1880 [NOI1995] 石子合并 && 区间dp

静悠 2022-02-16 阅读 32

 区间dp模板,f[i][j]表示[i, j]中最大得分,由于是环,可以把它展开成链,每次合并得分就是两堆的石子总数,很容易得到状态转移方程,f[i][j] = max(f[i][j], f[i][k] + f[k + 1][j] + d(i, j))

#include<bits/stdc++.h>
using namespace std;
#define rep(i,x,y); for(int i=x;i<=y;i++)
#define dec(i,x,y); for(int i=x;i>=y;i--)
#define int long long
#define Int __int128
#define INF 0x3f3f3f3f
#define lson(x) x << 1
#define rson(x) x << 1 | 1
#define FI first
#define SE second
#define mp make_pair
#define pb push_back
#define all(x) x.begin(), x.end()
typedef pair<int, int> PII;
int n, minl, maxl, f1[305][305], f2[305][305], num[305];
int s[305];
inline int d(int i, int j){return s[j] - s[i - 1];}
signed main(void){
    cin >> n;
    rep(i, 1, n){
        cin >> num[i];
        num[i + n] = num[i];
    }
    rep(i, 1, 2 * n){
        s[i] = s[i - 1] + num[i];
    }
    rep(p, 1, n - 1){
        for(int i = 1, j = i + p; j < 2 * n && i < 2 * n; i++, j = i + p){
            f2[i][j] = INF;
            rep(k, i, j - 1){
                f1[i][j] = max(f1[i][j], f1[i][k] + f1[k + 1][j] + d(i, j));
                f2[i][j] = min(f2[i][j], f2[i][k] + f2[k + 1][j] + d(i, j));
            }
        }
    }
    minl = INF;
    rep(i, 1, n){
        maxl = max(maxl, f1[i][i + n - 1]);
        minl = min(minl, f2[i][i + n - 1]);
    }
    cout << minl << "\n" << maxl << "\n";
}
举报

相关推荐

0 条评论