2017 ICPC hihocoder 1636

链接:https://hihocoder.com/problemset/problem/1636

石子归并变形版本。

在原有石子归并问题上。增加合并堆数的限制。

原有石子归并一次必须合并 2

现在一次必须合并 k k[L,R] ,也就是说合并的堆数不小于 L ,不大于R

每次合并的耗费。依然是石子总重。

那么显然合并前。我们需要知道。有多少堆合并了。

对于堆数不在 [L,R] 的,不能合并。

令: dp[k][l][r]

区间 [l,r] 合并成 k 段的耗费。

w[l,r]表示,区间 [l,r] 石子总重。

所以:
dp[k][l][r]=mint=l+k2r1(dp[k1][l][t]+dp[1][t+1][r])

特别的当:
dp[1][l][r]=mink=LR(dp[k][l][r]+w[l,r])

#include <algorithm>
#include <stdio.h>
#include <string.h>
#define MAXN 110
using namespace std;
const int INF=1e9;
int dp[MAXN][MAXN][MAXN];
int W[MAXN];
int D[MAXN];
int main ()
{
    int n,L,R;
    while(scanf("%d %d %d",&n,&L,&R)==3)
    {
        for(int i=0;i<=n;i++)
            for(int j=0;j<=n;j++)
                for(int k=0;k<=n;k++)
                        dp[i][j][k]=INF;
        for(int i=1;i<=n;i++)   scanf("%d",D+i);
        for(int i=1;i<=n;i++)   W[i]=W[i-1]+D[i];
        for(int k=1;k<=R;k++)
            for(int i=1,j=k;j<=n;i++,j++)   dp[k][i][j]=0;
        for(int len=L;len<=n;len++)
            for(int l=1,r=len;r<=n;r++,l++)
                for(int k=1;k<=R&&k<=len;k++)
                {
                    for(int t=l+k-2;t<r;t++)
                        if(dp[k][l][r]>(dp[k-1][l][t]+dp[1][t+1][r]))
                            dp[k][l][r]=dp[k-1][l][t]+dp[1][t+1][r];
                    if(k>=L&&dp[1][l][r]>dp[k][l][r]+W[r]-W[l-1])
                        dp[1][l][r]=dp[k][l][r]+W[r]-W[l-1];
                }
        int ans=INF;
        for(int i=L;i<=R;i++)ans=min(ans,dp[i][1][n]);
        if(ans>=INF)
            printf("0\n");
        else
            printf("%d\n",ans+W[n]-W[0]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值