Pangu and Stones UVALive - 8177 区间dp

link
石子合并变形,每次只能将[ L ,R ]堆石子合并为一堆.

在普通石子合并dp [i] [j]上 添加一维 dp[i][j][k] 表示i~j区间还剩k大堆的最小花费
那么dp[i][j][1]=min dp[i][j][z] l<=z<=r
而当k>1时转移的意义相当于不断划分石子,有转移方程
dp[i][j][k]=min dp[i][z][1]+dp[z+1][j][k-1]

#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define fi first
#define se second
#define pb push_back
using namespace std;
typedef long long ll;
typedef vector<int> VI;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const  ll inf  = 0x3f3f3f3f3f3f3f3f;
const int mod  = 998244353;
const int maxn = 1e6 + 4;
const int N    = 5e3 + 5;
const double eps = 1e-6;
const double pi = acos(-1.0);
ll qpow(ll x,ll y,ll mod){
    
    ll ans=1;x%=mod;while(y){
    
     if(y&1) ans=ans*x%mod; x=x*x%mod; y>>=1;}return ans;}


int n,l,r;
ll w[maxn],dp[110][110][110];
int main() {
    
    
    //freopen("RACE input.in","r",stdin);
    while(~scanf("%d%d%d",&n,&l,&r)) {
    
    
        for(int i=1;i<=n;i++) scanf("%lld",&w[i]),w[i]+=w[i-1];
        memset(dp,inf,sizeof dp);
        for(int i=1;i<=n;i++) dp[i][i][1]=0;
        for(int len=2;len<=n;len++) {
    
    
            for(int i=1;i+len-1<=n;i++) {
    
    
                int j=i+len-1;
                for(int k=len;k>=1;k--) {
    
    
                    if(k==1) {
    
    
                        for(int z=l;z<=r;z++) dp[i][j][1]=min(dp[i][j][1],dp[i][j][z]+w[j]-w[i-1]);
                    } else {
    
    
                        for(int z=i;z<j;z++)  dp[i][j][k]=min(dp[i][j][k],dp[i][z][1]+dp[z+1][j][k-1]);
                    }
                }
            }
        }
        printf("%lld\n",dp[1][n][1]>=inf?0:dp[1][n][1]);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_43914084/article/details/106793493