学了模板题之后上网搜下斜率优化dp的题目,然后就看到这道题,知道是斜率dp之后有思路就可以自己做不出来,要是不事先知道的话那就说不定了。

题意:给你n个数,一开始n个数相邻的数之间是被东西连着的,对于连着的一片的数,它们的价值就是两两乘积的和。所以4 5 1 2一开始就是4*5+4*1+4*2+5*1+5*2+1*2... 注意到两两乘积的和其实是可以这么算的((a1+a2+a3+..an)^2-(a1^2+a2^2+....))/2。现在我可以在数与数之间切m刀,问切完之后的最小价值是多少。

一个自然的想法是定义dp[n][t]表示的是前n个数被切了t刀的最小价值,不难发现方程是可以这么转移的

dp[i][t]=dp[j][t-1]+((sum[i]-sum[j])*(sum[i]-sum[j])-(d[i]-d[j]))/2  (j<i) 其中d[i]表示前i个数的平方的和

所以这个方程是1个三维的dp,对于1000的数据量是行不通的,所以仿照斜率优化的思路,我们可以尝试写出当 k<j时,j比k更优的方程,即:

dp[j][t-1]+((sum[i]-sum[j])*(sum[i]-sum[j])-(d[i]-d[j]))/2 < dp[k][t-1]+((sum[i]-sum[k])*(sum[i]-sum[k])-(d[i]-d[k]))/2

经过化简,我们可以得到一个这样的东西:

(2dp[j]+sum[j]^2+d[j])-(2dp[k]+sum[k]^2+d[k])/2*(sum[j]-sum[k])  <  sum[i]

显然又是一个斜率式子,利用先前推导的性质我们可以知道,我们每次更新的时候其实就是利用t-1层的信息推出t层的信息,推的时候实际有效的值也是一个下凸的点集,这个和上一题不一样之处就在于要更新m次,每次队列都要重新入队,但总体来说还是一样的,由于斜率优化后里层的dp达到线性,所以最后复杂度出来是O(n^2)的,仍然要注意之所以一开始可以弹队首是因为 sum[i]是递增的。

#pragma warning(disable:4996)
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <cmath>
using namespace std; #define ll long long
#define maxn 1100 ll dp[maxn][maxn];
ll a[maxn];
ll sum[maxn];
ll d[maxn]; int n, m; ll getup(int i, int j, int t){
return (2 * dp[i][t] + sum[i] * sum[i] + d[i]) - (2 * dp[j][t] + sum[j] * sum[j] + d[j]);
} ll getdown(int i, int j){
return 2 * (sum[i] - sum[j]);
} int que[maxn];
int qh, qt; int main()
{
while (cin >> n >> m&&(n||m)){
a[0] = d[0] = sum[0] = 0;
for (int i = 1; i <= n; ++i){
scanf("%I64d", &a[i]);
sum[i] = sum[i - 1] + a[i];
d[i] = d[i - 1] + a[i] * a[i];
}
dp[0][0] = 0;
for (int i = 1; i <= n; ++i){
dp[i][0] = dp[i - 1][0] + a[i] * sum[i - 1];
}
for (int x = 1; x <= m; ++x){
dp[0][x] = 0;
qh = qt = 0;
que[qt++] = 0;
for (int i = 1; i <= n; ++i){
while (qh + 1 < qt && getup(que[qh + 1], que[qh], x - 1) <= sum[i] * getdown(que[qh + 1], que[qh])){
qh++;
}
dp[i][x] = dp[que[qh]][x - 1] + ((sum[i] - sum[que[qh]])*(sum[i] - sum[que[qh]]) - (d[i] - d[que[qh]])) / 2;
while (qh + 1 < qt && getup(i, que[qt - 1], x - 1)*getdown(que[qt - 1], que[qt - 2]) <= getup(que[qt - 1], que[qt - 2], x - 1)*getdown(i, que[qt - 1])){
qt--;
}
que[qt++] = i;
}
}
printf("%I64d\n", dp[n][m]);
}
return 0;
}

HDU2829 Lawrence(斜率优化dp)的更多相关文章

  1. HDU2829 Lawrence —— 斜率优化DP

    题目链接:https://vjudge.net/problem/HDU-2829 Lawrence Time Limit: 2000/1000 MS (Java/Others)    Memory L ...

  2. hdu 2829 Lawrence(斜率优化DP)

    题目链接:hdu 2829 Lawrence 题意: 在一条直线型的铁路上,每个站点有各自的权重num[i],每一段铁路(边)的权重(题目上说是战略价值什么的好像)是能经过这条边的所有站点的乘积之和. ...

  3. HDU 2829 Lawrence (斜率优化DP或四边形不等式优化DP)

    题意:给定 n 个数,要你将其分成m + 1组,要求每组数必须是连续的而且要求得到的价值最小.一组数的价值定义为该组内任意两个数乘积之和,如果某组中仅有一个数,那么该组数的价值为0. 析:DP状态方程 ...

  4. 【转】斜率优化DP和四边形不等式优化DP整理

    (自己的理解:首先考虑单调队列,不行时考虑斜率,再不行就考虑不等式什么的东西) 当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重 ...

  5. bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)

    题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地 ...

  6. bzoj-1096 1096: [ZJOI2007]仓库建设(斜率优化dp)

    题目链接: 1096: [ZJOI2007]仓库建设 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L ...

  7. [BZOJ3156]防御准备(斜率优化DP)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3156 分析: 简单的斜率优化DP

  8. 【BZOJ-1096】仓库建设 斜率优化DP

    1096: [ZJOI2007]仓库建设 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3719  Solved: 1633[Submit][Stat ...

  9. BZOJ 1010: [HNOI2008]玩具装箱toy 斜率优化DP

    1010: [HNOI2008]玩具装箱toy Description P教授要去看奥运,但是他舍不下他的玩具,于是他决定把所有的玩具运到北京.他使用自己的压缩器进行压缩,其可以将任意物品变成一堆,再 ...

随机推荐

  1. 【转】oracle connect by用法

    今天偶然看到connect by,但记不太清楚具体用法了.转了个博客(写的蛮好的),当作笔记. http://www.cnblogs.com/linjiqin/p/3152690.html 先用sco ...

  2. 在Linux上安装JDK7

    查看是否安装了JDK 如果安装完毕后,jdk版本不是当前所安装的,则需要卸载之前linux自带的jdk版本,因为安装Redhat9后默认安装了jdk, 可是默认安装的jdk1.4版本比较老,所以需要先 ...

  3. ES5 vs ES6

    ES5中 var React = require('react-native'); ES6中 import React from 'react-native'; .babelrc文件中添加一下内容 { ...

  4. RTP、RTCP

    http://blog.chinaunix.net/uid-22670933-id-1771676.html

  5. sublime3快捷键

    Ctrl+D 选中光标所占的文本,继续操作则会选中下一个相同的文本. Alt+F3 选中文本按下快捷键,即可一次性选择全部的相同文本进行同时编辑.举个栗子:快速选中并更改所有相同的变量名.函数名等. ...

  6. iOS 七大手势之轻拍,长按,旋转手势识别器方法

    一.监听触摸事件的做法   如果想监听一个view上面的触摸事件,之前的做法通常是:先自定义一个view,然后再实现view的touches方法,在方法内部实现具体处理代码 通过touches方法监听 ...

  7. 自己编写基于MVC的轻量级PHP框架

    做WEB开发已有三年,每次都写重复的东西, 因此,想自己写一下框架,以后开发方便.本人之前asp.NET一年开发,jsp半年,可是后来因为工作的原故换成PHP.其实很不喜欢PHP的语法.还有PHP的函 ...

  8. 无法解决“Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed”与“Newtonsoft.Json, Version=4.5.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed”之间的冲突。正在随意选择“Newtonsoft.Jso

    今天的程序莫名报错:  无法解决“Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed” ...

  9. svn merge和branch

    http://www.cnblogs.com/cxd4321/archive/2012/07/12/2588110.html 使用svn几年了,一直对分支和合并敬而远之,一来是因为分支的管理不该我操心 ...

  10. 硬件描述语言Verilog设计经验总结

    一.硬件描述语言Verilog 粗略地看Verilog与C语言有许多相似之处.分号用于结束每个语句,注释符也是相同的(/* ... */和// 都是熟悉的),运算符"=="也用来测 ...