题意: 给n(n<=10^6)个非负数字,放在一个数组num中,再给一个特殊值m。求将这个数组分成任意多个区间,每个区间[a,b]的值定义为( sigma(num[i] | (a<=i<=b)) ) ^ 2 + m.要区间值总和最小,并输出此最小值  (PS:这道题不用考虑暴int问题,当然这是AC以后才发现的)。

解题思路: 定义sum[i]=sigma(num[j] | (1<=j<=i)) (这里假设num数组下标从1开始)

     定义f(j,i) = (sum[i]-sum[j])^2+m (区间[j+1,i]的值)

     定义dp[i]为从1到i这段的题意要求的那个最小值,根据其定义就有dp[i]=min{ dp[j]+f(j,i) | 0<=j<i } (****)。(思考为什么这样定义?)

     另外定义一个仅作标识用的量dp[j,i],表示从j到i这段题意要求的最小区间值和,即dp[1,k]=dp[k]。

裸的枚举当然是不科学的,效率太低。与上一篇博客略有类似,计算dp[i]要用以前的结果,如何对要枚举的状态进行优化呢?

令(k<j<i) ,x>0;

  1. 若有dp[k]+f(k,i)> dp[j]+f(j,i),那么一定有dp[i+x] > dp[k]+f(k+1,x+i); 也就是说 k一定不是对应着i的一个可能最优解。 在求解dp[i+x]时,k点就不用枚举了。
  2. 若有dp[k]+f(k,i)<= dp[j]+f(j,i),那么一定有dp[i+x] > dp[j]+f(j,i+x)。

重新思考一下(****)中dp[i]的定义,应用数学归纳法:

dp[1]=f(0,1) 或者dp[1]=f(0,1)+dp[0] (dp[0]=0)

dp[2]=min{dp[1]+f(2,2),dp[0]+f(1,2)} (刚好对应两种区间拆分方式)

假设dp[k]用上式定义也正确,那么

  dp[k+1]=min{ dp[1,j]+dp[j+1,k+1] | (j <= k) },如果dp[j+1,k+1]==f(j,k+1),原式自然成立;

  那即使不成立呢? 也就是说存在一个j<jj<k, 使得dp[j+1,k+1]==f(j,jj)+dp[jj+1,k+1],所以

   dp[1,j]+f(j,jj)+dp[jj+1,k+1]描述的是什么呢?dp[1,j]+f(j,jj)正是dp[jj]的一个可能最优解。dp[k+1]=min{dp[jj]+dp[jj+1,k+1], dp[k+1] },原式成立!

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=;
int num[maxn],pl;
int sum[maxn];
int dp[maxn];
int que[maxn];
int f(int j,int i){
return (sum[i]-sum[j])*(sum[i]-sum[j])+pl;
}
int gety(int j,int k){
return dp[j]+sum[j]*sum[j]-dp[k]-sum[k]*sum[k];
}
int getx(int j,int k){
return (sum[j]-sum[k])<<;
}
int main()
{
int n;
while(scanf("%d%d",&n,&pl) != EOF){
for(int i=;i<=n;i++)
scanf("%d",&num[i]);
sum[]=dp[]=;
for(int i=;i<=n;i++)
sum[i]=sum[i-]+num[i];
int head=,tail=;
que[tail++]=;
for(int i=;i<=n;i++){
while(head+ < tail && gety(que[head+],que[head])<=getx(que[head+],que[head])*sum[i])
head++;
dp[i]=dp[que[head]]+f(que[head],i);
while((head+ < tail) && gety(i,que[tail-])*getx(que[tail-],que[tail-])<=gety(que[tail-],que[tail-])*getx(i,que[tail-]))
tail--;
que[tail++]=i;
}
printf("%d\n",dp[n]);
}
return ;
}

hdu3507的更多相关文章

  1. 【hdu3507】Print Article 【斜率优化dp】

    题意 https://cn.vjudge.net/problem/HDU-3507 分析 斜率优化的模板题 #include <cstdio> #include <cstring&g ...

  2. hdu3507(初识斜率优化DP)

    hdu3507 题意 给出 N 个数字,输出的时候可以选择连续的输出,每连续输出一串,它的费用是 这串数字和的平方加上一个常数 M. 分析 斜率优化dp,入门题. 参考 参考 得到 dp 方程后,发现 ...

  3. HDU3507 Print Article —— 斜率优化DP

    题目链接:https://vjudge.net/problem/HDU-3507 Print Article Time Limit: 9000/3000 MS (Java/Others)    Mem ...

  4. c++之路进阶——hdu3507(Print Article)

    参考博文:http://www.cnblogs.com/ka200812/archive/2012/08/03/2621345.html//讲的真的很好,有个小错误,博客里的num全为sum,像我这种 ...

  5. HDU3507 print artical

    题目大意:有N个数字a[N],每输出连续的一串,它的费用是 “这行数字的平方加上一个常数M”.问如何输出使得总费用最小.(n<=500000) 分析:动态规划方程为:dp[i]=dp[j]+M+ ...

  6. HDU3507 Print Article(斜率优化dp)

    前几天做多校,知道了这世界上存在dp的优化这样的说法,了解了四边形优化dp,所以今天顺带做一道典型的斜率优化,在百度打斜率优化dp,首先弹出来的就是下面这个网址:http://www.cnblogs. ...

  7. hdu3507 Print Article(斜率DP优化)

    Zero has an old printer that doesn't work well sometimes. As it is antique, he still like to use it ...

  8. HDU3507 Print Article (斜率优化DP基础复习)

    pid=3507">传送门 大意:打印一篇文章,连续打印一堆字的花费是这一堆的和的平方加上一个常数M. 首先我们写出状态转移方程 :f[i]=f[j]+(sum[i]−sum[j])2 ...

  9. hdu3507 Print Article

    Print Article Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others) P ...

随机推荐

  1. Jquery弹窗插件Lhgdialog的用法

    Lhgdialog的用法 大家都知道用js可以实现,但是在使用js实现的弹窗时得考虑很东西:浏览器的兼容.页面的交互等等问题. 在这里简单介绍一下lhgdialog的用法. 参数有: Title:弹窗 ...

  2. Copy from chromium-dev!

    https://app.yinxiang.com/pub/gguangle0/chromium-dev 做了一些搬运工的活..............

  3. shape和selector是Android UI设计中经常用到的

    shape和selector是Android UI设计中经常用到的,比如我们要自定义一个圆角Button,点击Button有些效果的变化,就要用到shape和selector.可以这样说,shape和 ...

  4. UVA 10163 Storage Keepers(dp + 背包)

    Problem C.Storage Keepers  Background Randy Company has N (1<=N<=100) storages. Company wants ...

  5. MPAndroidChart绘制图形表

    最近一个项目需要用到表格进行统计显示,本来用的是的achartengine,后来发现一个更加强大的开源框架MPAndroidChart. 下面简单介绍下MPAndroidChart,MPAndroid ...

  6. Unity大中华区主办 第二届Unity 游戏及应用大赛 实力派精品手游盘点

    Unity是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏.建筑可视化.实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专业游戏引擎.包含如今时 ...

  7. php 实现二进制加法运算

    php实现二进制加法: 思路:没有工作中应用过此场景,但十进制的加法还是经常做的,能不能用十进制加法变相实现呢? 答案是可以的,并且php也提供进制间转换的函数,我的实现使用了 bindec():二进 ...

  8. Matlab工程

    1.matlab设置默认路径 在原来的默认路径(bin)下创建一个名为startup.m的文件,内容为相对路径 cd ..\..\WorkSpace\ 或绝对路径 cd F:\Program\MATL ...

  9. OpenCV系列--摄像头控制的简单代码

    操作系统:windows xp 开发工具:VS2008 opencv版本:2.1.0 依赖库:OpenCV2.1\lib\highgui.lib #include "cv.h" # ...

  10. leetcode Remove Duplicates from Sorted Array python

    class Solution(object): def removeDuplicates(self,nums): if len(nums) <= 0: return 0 j=0 for i in ...