2017北京赛区J题

类型:三维动态规划

题目链接

题意:

合并连续石头块,最终要合并成一块,求时间最短,每次只能连续合并L~R块石头,不能合并成一块时输出-1

题解:

  • 利用动态规划解决两种分问题
  • dp[l][r][k]:表示在区间l到r之间分成k堆石头的最小代价
  • 当k=1时,转移方程为:dp[l][r][1]=min(dp[l][r][1],dp[l][i][x-1]+dp[i+1][r][1]+sum[l][r]);
  • 当k>=2时,转移方程为:dp[l][r][k]=min(dp[l][r][k],dp[l][i][k-1]+dp[i+1][r][1]);
  • 先dp当k=1的情况,然后还要从其l和r之间的间隔先枚举。

#include<bits/stdc++.h>
using namespace std;
int sum[105][105];
int a[105];
const int inf = 0x3f3f3f3f;
int dp[105][105][105];
int main()
{
    int n,L,R;
    while(scanf("%d%d%d",&n,&L,&R)!=EOF)
    {
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        memset(dp,inf,sizeof(dp));
         for(int i=1;i<=n;i++)
        {
            sum[i][i-1]=0;
            for(int j=i;j<=n;j++)
            {
                sum[i][j]=sum[i][j-1]+a[j];
                dp[i][j][j-i+1]=0;
            }
        }
    int l,r;
    for(int d=0;d<=n;d++)//枚举间距
    {
        for(l=0;l+d<=n;l++)//枚举l
        {
            r=l+d;
            for(int i=l;i<r;i++)//枚举中间位置
            {
                for(int x=L;x<=R;x++)//一堆的dp
                {
                    dp[l][r][1]=min(dp[l][r][1],dp[l][i][x-1]+dp[i+1][r][1]+sum[l][r]);
                }
                for(int k=2;k<=r-l+1;k++)//多堆的dp
                        dp[l][r][k]=min(dp[l][r][k],dp[l][i][k-1]+dp[i+1][r][1]);
            }
        }
    }
        if(dp[1][n][1]==inf) printf("0
");
        else printf("%d
",dp[1][n][1]);
    }
return 0;
}

原文地址:https://www.cnblogs.com/q1076452761/p/7888080.html