• 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]);
        }
    }
    
  • 相关阅读:
    PHP应用目录结构设计
    php 项目性能优化
    Zend Framework的PHP编码规范【1】
    php 如何做在线人数统计
    linux 文件权限
    总结:常用的通用数据处理指令
    全排列(含递归和非递归的解法)
    局部变量,静态局部变量,全局变量,静态全局变量在内存中的存放区别(转)
    C++中引用详解
    Pascal三角形
  • 原文地址:https://www.cnblogs.com/kuronekonano/p/11135846.html
Copyright © 2020-2023  润新知