题意: 给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. 飘逸的python - 两种with语句实现方法

    第一种是实现上下文管理器协议,即魔法方法__enter__和__exit__. class Foo: def __enter__(self): print 'in' def __exit__(self ...

  2. SqlServer导库语句

    GO /****** 对象: StoredProcedure [dbo].[sp_ExportDatabase] 脚本日期: 07/18/2013 12:37:26 ******/ SET ANSI_ ...

  3. EBS R12 怎么修改APPS密码

    apps 和 applsys 的口令 $> FNDCPASS apps/<apps password> 0 Y system/<system password> SYST ...

  4. 在struts2中整合ajax时出现Template /template/ajax/head.ftl not found错误时的处理方法

    Struts2 Ajax出现错误“Template /template/ajax/head.ftl not found” 2013-02-08 18:26:27|  分类: 默认分类|字号 订阅   ...

  5. hadoop笔记之Hive的管理(web界面方式)

    Hive的管理(二) Hive的管理(二) Web界面方式 端口号9999 启动方式:hive --service hwi 通过浏览器来访问:http://<IP地址>:9999/hwi/ ...

  6. mysql函数操作(3)

    <?php $dbh = new PDO('mysql:dbname=testdb;host=localhost', 'mysql_user', 'mysql_pwd'); $dbh->s ...

  7. xunsearch安装与卸载

    刚接触xunsearch(迅搜)的时候,我是排斥的.排斥的原因不是因为害怕学习新技术(其实我是对心技术很感兴趣),而是因为:一方面xunsearch是国人开发的,对于国人写的开源产品,我不是太感兴趣( ...

  8. java面向对象之 继承 Inheritance

    对象的一个新类可以从现有的类中派生,这个过程称为类继承.新类继承了原始类的特性,新类称为原始类的派生类(子类),而原始类称为新类的基类(父类).派生类可以从它的基类那里继承方法和实例变量,并且类可以修 ...

  9. oracle 游标-------转

    -- 声明游标:CURSOR cursor_name IS select_statement --For 循环游标 --(1)定义游标 --(2)定义游标变量 --(3)使用for循环来使用这个游标 ...

  10. MYSQL 引擎的情况

    方法 1: show engine innodb status; ------------------------------------------------------------------- ...