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的线性方 ...
随机推荐
- [Luogu5686] 和积和
Description 给定两个下标从\(1\)到\(n\)编号的序列 \(a_i,b_i\),定义函数\(S(l,r)(1\le l\le r\le n)\)为: \[\sum_{i=l}^r a_ ...
- python cx_oracle 环境搭建
背景说明: 之前的环境本来是可以用的,是另外一个项目(python27)需要的时候搭建的.新项目采用的是python36,安装的cx_oracle的版本是7,而环境中的Oracle客户端是11,导致p ...
- QThread::wait(),一直以来我以为它阻塞的是QThread对象,可是我现在明白,原来阻塞的是这个对象所在的线程(通常是主线程)——所有事情源于 QThread 的事件循环——如果使用继承QThread这一方法,QThread::quit()没有效果,因为这个线程根本就不需要事件循环
近日,使用QThread,一些问题百思不得其解,看过大牛的文章,恍然大悟啊. 原文 http://hi.baidu.com/dbzhang800/item/c14c97dd15318d17e1f46f ...
- mysql添加索引造成的影响
尽管添加索引可以优化SQL语句的性能,但是添加索引的同时也会带来不小的开销.尤其是在有大量的索引的情况下. mysql添加索引造成的影响如下: 1.DML(数据操作语言)影响,在表上添加缩影会直接影响 ...
- Collection接口的子接口——Set接口
https://docs.oracle.com/javase/8/docs/api/java/util/Set.html public interface Set<E> extends ...
- JDK8~13新特性概览
JDK8 1. 接口default 与 static 关键字 /** * jdk8中接口可以使用声明default和static修饰的方法 * static修饰的方法和普通的方法一样,可以被直接调用 ...
- abap 优化之ST05
DATA: gt_mara TYPE TABLE OF mara. SELECT * INTO TABLE gt_mara FROM mara WHERE MATKL = 'L000001' %_hi ...
- 惟一ID生成方法
几乎所有的业务系统,都存在生成惟一ID的需求,例如: 用户ID:user_id 订单ID: order_id 消息ID: msg_id 常见的ID生成有三大类方法: 一.中间件实现 1.利用Mysql ...
- mybatis原理解析
本文是结合spring-mybatis整合进行的分析 1.先看看依赖的jar包: <dependency> <groupId>org.mybatis</groupId&g ...
- 从0开始Jmeter接口测试实战
在之前的文章中给大家介绍过接口测试文档和接口测试用例示例,本文基于Jmeter工具给大家介绍一下如何实现接口测试用例:包括发起Http请求,绕过登陆,验证响应.JMeter是Apache组织开发的基于 ...