UPC-5843: 摘樱桃(最优状态递推)

这里写图片描述

很难想到的最优状态递推,一开始总在如何分组的问题上纠结。其实只需要在分配第i个樱桃时,将其与前一个(j=i-1)分为一组、前两个分为一组(j=i-2),前三个分为一组(j=i-3)。。。。然后取剩下j个的最优分配情况dp[j]求和取最小值即可。
dp【j】表示了当有j个樱桃时的最优解分配。(是做了-T且平方处理的最终结果)
用一个前缀和数组sum存储前N项前缀和,通过作差可以得到i到j区间的总和,遍历i到j不断取区间和当做使当前第i个樱桃与之前j个分为一组,然后再次基础上-T并平方,与第j-1个樱桃时的最优解进行求和,得到第i个时的最优解的临时值,直到遍历完成,取合并后的最小值即当前i个的最优解。

代码如下:

#include<stdio.h>///类似最长递增子序列的递推,不用考虑分组问题,不断对其递推最优解即可
#include<math.h>
#include<algorithm>
#include<string.h>
using namespace std;
int n,t,a[1005],dp[1005],sum[1005];
int main()
{
    while(scanf("%d%d",&n,&t)!=EOF)
    {
        memset(dp,0x3f,sizeof(dp));///因为求最小值,因此初始化为最大值
        for(int i=1; i<=n; i++) scanf("%d",&a[i]),sum[i]=sum[i-1]+a[i];///前缀和计算
        dp[1]=(a[1]-t)*(a[1]-t);///只有一个樱桃时只有一种解
        dp[0]=0;
        for(int i=2; i<=n; i++)///有i个樱桃时的最优解
            for(int j=i-1; j>=0; j--)///第i个樱桃与j个樱桃合为一组,再加上剩余樱桃的最优解,不断遍历合并取最小值
                dp[i]=min(dp[i],(sum[i]-sum[j]-t)*(sum[i]-sum[j]-t)+dp[j]);///当前dp【i】的解,和其他分配方案的解,取最优解
        printf("%d\n",dp[n]);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值