N - Slimes.atcoder Dp题单

https://atcoder.jp/contests/dp

题目大意

https://atcoder.jp/contests/dp/tasks/dp_n
给你一组数据,这个数据相邻两个合并,合并的代价是这两个的数值和
求最小代价
这个是超级经典的区间dp,所以写下来

code

void solve(){
    int n;cin>>n;
    vector<int>a(n+1),pre(n+1);
    vector<vector<int>>f(n+1,vector<int>(n+1));
    for(int i=1;i<=n;i++){
        cin>>a[i];
        pre[i]=pre[i-1]+a[i];
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            f[i][j]=1e18;
        }
        f[i][i]=0;
    }
    for(int i=n;i>=1;i--){
        for(int j=i+1;j<=n;j++){
            for(int k=i;k<j;k++)
            f[i][j]=min(f[i][j],f[i][k]+f[k+1][j]+pre[j]-pre[i-1]);
        }
    }
    cout<<f[1][n]<<endl;
}

分析

对于每个区间(i,j)其最小的合并代价,就是等于两个子区间的合并代价,加上j到i的和(这里用前缀和)
枚举左端点i右端点j以及他们中间的某个位置k,然后取min
之所以i是倒着的是因为在你计算i=1作为左端点的时候,你得先知道他的子区间(比如2作为左端点)的代价,所以要反过来

posted @ 2026-04-01 12:25  Time_q  阅读(14)  评论(0)    收藏  举报