zoukankan      html  css  js  c++  java
  • 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
    ",dp[n]);
        }
    }
    
  • 相关阅读:
    Java知识体系总结(2021版)
    第三篇 makefile的伪目标
    第二篇 makefile的基本结构
    第一篇 make与makefile介绍
    hdu 1994 利息计算
    Python中Class中的object是什么意思?
    编译语言和解释语言有什么不同?
    从文本文件hello.txt到可执行文件hello
    classmethod和staticmethod
    Uninstall NetBeans
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135846.html
Copyright © 2011-2022 走看看