HDU 2829 [Lawrence] DP斜率优化
解题思路
首先肯定是考虑如何快速求出一段铁路的价值。
\]
那么我们要维护如下两个东西,就可以在\(O(1)\)内求出一段铁路的价值了。
for( LL i = 1; i <= N; ++i ) Sum[ i ] = Sum[ i - 1 ] + A[ i ];
for( LL i = 1; i <= N; ++i ) SumOfSqr[ i ] = SumOfSqr[ i - 1 ] + A[ i ] * A[ i ];
然后我们考虑打一个最暴力的DP。
我们令\(F[i][j]\)为到第\(i\)个仓库,炸了\(j\)次的最小总价值:
for( LL i = 1; i <= N; ++i )
F[ i ][ 0 ] = Sum[ i ] * Sum[ i ] - SumOfSqr[ i ];
for( LL j = 1; j <= M; ++j )
for( LL i = j + 1; j <= N; ++j ) {
F[ i ][ j ] = INF;
for( LL k = j; k < i; ++k )
F[ i ][ j ] = min( F[ i ][ j ], F[ k ][ j - 1 ] + sqr( Sum[ i ] - Sum[ k ] ) - ( SumOfSqr[ i ] - SumOfSqr[ k ] ) );
}
Ans = F[ N ][ M ];
为了节省空间,我们滚动掉一维:
for( LL i = 1; i <= N; ++i )
F1[ i ] = Sum[ i ] * Sum[ i ] - SumOfSqr[ i ];
for( LL j = 1; j <= M; ++j ) {
for( LL i = j + 1; j <= N; ++j ) {
F2[ i ] = INF;
for( LL k = j; k < i; ++k )
F2[ i ] = min( F2[ i ], F1[ k ] + sqr( Sum[ i ] - Sum[ k ] ) - ( SumOfSqr[ i ] - SumOfSqr[ k ] ) );
}
memcpy( F1, F2, sizeof( F2 ) );
}
Ans = F1[ N ];
最后考虑优化转移复杂度:
设\(l > k\),且从\(l\)转移优于从\(k\)转移,那么就有:
\]
\]
\]
然后我们就可以进行斜率优化了。
斜率优化的具体讲解见这里。
参考程序
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const LL Maxn = 1010;
LL n, m;
LL A[ Maxn ], Sum[ Maxn ], SumOfSqr[ Maxn ], F1[ Maxn ], F2[ Maxn ];
LL L, R, Queue[ Maxn ];
inline LL Sqr( LL x ) { return x * x; }
inline LL GetSum( LL r, LL l ) {
return Sqr( Sum[ r ] - Sum[ l ] ) - ( SumOfSqr[ r ] - SumOfSqr[ l ] );
}
inline bool Less( LL i, LL j, LL T ) {
LL X = 2 * ( Sum[ j ] - Sum[ i ] );
LL Y = ( F1[ j ] + Sqr( Sum[ j ] ) + SumOfSqr[ j ] ) -
( F1[ i ] + Sqr( Sum[ i ] ) + SumOfSqr[ i ] );
return Y < T * X;
}
inline bool Greater( LL i, LL j, LL k ) {
LL X1 = 2 * ( Sum[ j ] - Sum[ i ] );
LL Y1 = ( F1[ j ] + Sqr( Sum[ j ] ) + SumOfSqr[ j ] ) -
( F1[ i ] + Sqr( Sum[ i ] ) + SumOfSqr[ i ] );
LL X2 = 2 * ( Sum[ k ] - Sum[ j ] );
LL Y2 = ( F1[ k ] + Sqr( Sum[ k ] ) + SumOfSqr[ k ] ) -
( F1[ j ] + Sqr( Sum[ j ] ) + SumOfSqr[ j ] );
return X2 * Y1 >= X1 * Y2;
}
void Work() {
for( LL i = 1; i <= n; ++i ) scanf( "%lld", &A[ i ] );
Sum[ 0 ] = 0; SumOfSqr[ 0 ] = 0;
for( LL i = 1; i <= n; ++i ) Sum[ i ] = Sum[ i - 1 ] + A[ i ];
for( LL i = 1; i <= n; ++i ) SumOfSqr[ i ] = SumOfSqr[ i - 1 ] + Sqr( A[ i ] );
for( LL i = 1; i <= n; ++i )
F1[ i ] = GetSum( i, 0 );
for( LL j = 1; j <= m; ++j ) {
L = R = 0; Queue[ R++ ] = j;
memset( F2, 0, sizeof( F2 ) );
for( LL i = j + 1; i <= n; ++i ) {
while( L + 1 < R && Less( Queue[ L ], Queue[ L + 1 ], Sum[ i ] ) )
++L;
F2[ i ] = F1[ Queue[ L ] ] + GetSum( i, Queue[ L ] );
while( L + 1 < R && Greater( Queue[ R - 2 ], Queue[ R - 1 ], i ) )
--R;
Queue[ R++ ] = i;
}
memcpy( F1, F2, sizeof( F2 ) );
}
printf( "%lld\n", F1[ n ] / 2 );
return;
}
int main() {
scanf( "%lld%lld", &n, &m );
while( !( n == 0 && m == 0 ) ) {
Work();
scanf( "%lld%lld", &n, &m );
}
return 0;
}
HDU 2829 [Lawrence] DP斜率优化的更多相关文章
- HDU.2829.Lawrence(DP 斜率优化)
题目链接 \(Description\) 给定一个\(n\)个数的序列,最多将序列分为\(m+1\)段,每段的价值是这段中所有数两两相乘的和.求最小总价值. \(Solution\) 写到这突然懒得写 ...
- HDU 2829 Lawrence(斜率优化DP O(n^2))
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2829 题目大意:有一段铁路有n个站,每个站可以往其他站运送粮草,现在要炸掉m条路使得粮草补给最小,粮草 ...
- HDU 3480 Division DP斜率优化
解题思路 第一步显然是将原数组排序嘛--然后分成一些不相交的子集,这样显然最小.重点是怎么分. 首先,我们写出一个最暴力的\(DP\): 我们令$F[ i ][ j ] $ 为到第\(i\)位,分成\ ...
- hdu 2829 Lawrence(四边形不等式优化dp)
T. E. Lawrence was a controversial figure during World War I. He was a British officer who served in ...
- HDU 2829 Lawrence (斜率DP)
斜率DP 设dp[i][j]表示前i点,炸掉j条边的最小值.j<i dp[i][j]=min{dp[k][j-1]+cost[k+1][i]} 又由得出cost[1][i]=cost[1][k] ...
- hdu 2829 Lawrence(斜率优化DP)
题目链接:hdu 2829 Lawrence 题意: 在一条直线型的铁路上,每个站点有各自的权重num[i],每一段铁路(边)的权重(题目上说是战略价值什么的好像)是能经过这条边的所有站点的乘积之和. ...
- HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化
HDU 2829 区间DP & 前缀和优化 & 四边形不等式优化 n个节点n-1条线性边,炸掉M条边也就是分为m+1个区间 问你各个区间的总策略值最少的炸法 就题目本身而言,中规中矩的 ...
- HDU 3507 [Print Article]DP斜率优化
题目大意 给定一个长度为\(n(n \leqslant 500000)\)的数列,将其分割为连续的若干份,使得 $ \sum ((\sum_{i=j}^kC_i) +M) $ 最小.其中\(C_i\) ...
- HDU 3507 单调队列 斜率优化
斜率优化的模板题 给出n个数以及M,你可以将这些数划分成几个区间,每个区间的值是里面数的和的平方+M,问所有区间值总和最小是多少. 如果不考虑平方,那么我们显然可以使用队列维护单调性,优化DP的线性方 ...
随机推荐
- 【pytorch】学习笔记(一)-张量
pytorch入门 什么是pytorch PyTorch 是一个基于 Python 的科学计算包,主要定位两类人群: NumPy 的替代品,可以利用 GPU 的性能进行计算. 深度学习研究平台拥有足够 ...
- win10自带虚拟机的使用(Hyper-v)
昨天刚发现的觉得特别好用,故推荐一下,跟VM虚拟机的使用方法是一样的 1.点击开始菜单中的<设置>图标,进入设置页码 2.点击<应用>图标,进入应用页码,并找到程序和功能 3. ...
- spark算子篇-aggregate 系列
aggregate aggregate 是比较常用的 行动 操作,不是很好懂,这里做个解释. aggregate(zeroValue, seqOp, combOp) zeroValue 是一个初始值, ...
- GridView中点击某行的任意位置就选中该行
GridView中点击某行的任意位置就选中该行 -- :: 分类: 第一步:添加选择列 点击GridView右边小尖头,双击CommandField,选中"选择",添加,将起设置为不可见: 第二步:处 ...
- powerDisgner 数据类型对比
powerDisgner 16.5版本支持一下类型数据模型格式 以下数字数据类型可用: Standard data type DBMS-specific physical data type Cont ...
- CSDN添加文章目录
在发表的文章中,系统根据文章中H1到H6标签自动生成文章目录. 一.发表文章的时候合理使用“标题”标签. 二.目录生成.只要在文章中使用了“标题1”这样的功能,就可以在博文开头看到文章的目录.
- docker 入门(1)
1,docker 的安装卸载 https://docs.docker.com/install/linux/docker-ce/ubuntu/ 2,docker中的基本概念 镜像(Image) 容器(C ...
- HackIM web关writeup
Web100 访问页面将看到下面的错误 在burp里使用request / response查看有没有什么不正常的地方.如下图所示,在返回的数据包里被设置了两次不同的PHPSESSID. 如果我把PH ...
- 关于Linux单机、集群部署FastDFS分布式文件系统的步骤。
集群部署:2台tarcker服务器,2台storage服务器. 192.168.201.86 ---------(trackerd+storage+nginx) 192.168.201.87 ...
- MySQL字段值按照拼音首字母排序
最简单.快速的方法: 将需要进行排序的字段编码设置为GBK,然后在查询时直接使用asc/desc就可以啦