HDU 3480 Division DP斜率优化
解题思路
第一步显然是将原数组排序嘛……然后分成一些不相交的子集,这样显然最小。重点是怎么分。
首先,我们写出一个最暴力的\(DP\):
我们令$F[ i ][ j ] $ 为到第\(i\)位,分成\(j\)组的代价,我们可以写出如下 $ DP$
for( LL i = 1; i <= N; ++i ) F[ i ][ 1 ] = sqr( A[ i ] - A[ 1 ] );
for( LL j = 2; j <= M; ++j )
for( LL i = j; i <= N; ++i ) {
F[ i ][ j ] = INF;
for( LL k = j - 1; k <= i - 1; ++k )
F[ i ][ j ] = min( F[ i ][ j ], F[ k ][ j - 1 ] + sqr( A[ j ] - A[ k + 1 ] ) );
}
滚动掉一维节省空间:
for( LL i = 1; i <= N; ++i ) F1[ i ] = sqr( A[ i ] - A[ 1 ] );
for( LL j = 2; j <= M; ++j ) {
for( LL i = j; i <= N; ++i ) {
F2[ i ] = INF;
for( LL k = j - 1; k <= i - 1; ++k )
F2[ i ] = min( F2[ i ], F1[ K ] + sqr( A[ j ] - A[ k + 1 ] ) );
}
memcpy( F1, F2, sizeof( F2 ) );
}
但是时间上依然难以接受。我们考虑优化最内层的转移复杂度。
不妨设转移的时候\(l>k\)且从\(l\)转移优于从\(k\)转移,那么我们就能得到如下不等式:
\]
化简,得
\]
所以我们可以进行斜率优化。具体优化讲解可以看这里。过程十分相似。
参考程序
#include <bits/stdc++.h>
#define LL long long
using namespace std;
LL N, M, A[ 10010 ], F1[ 10010 ], F2[ 10010 ];
LL L, R, Queue[ 10010 ];
inline LL sqr( LL x ) { return x * x; }
inline void Clear() {
memset( A, 0, sizeof( A ) );
memset( F1, 0, sizeof( F1 ) );
return;
}
inline void Clear2() {
memset( Queue, 0, sizeof( Queue ) );
memset( F2, 0, sizeof( F2 ) );
L = R = 0;
return;
}
inline bool Less( LL i, LL j, LL T ) {
LL DeltaX = 2 * ( A[ j + 1 ] - A[ i + 1 ] );
LL DeltaY = F1[ j ] - F1[ i ] + sqr( A[ j + 1 ] ) - sqr( A[ i + 1 ] );
return DeltaY < T * DeltaX;
}
inline bool Greater( LL i, LL j, LL k ) {
LL DeltaX1 = 2 * ( A[ j + 1 ] - A[ i + 1 ] );
LL DeltaX2 = 2 * ( A[ k + 1 ] - A[ j + 1 ] );
LL DeltaY1 = F1[ j ] - F1[ i ] + sqr( A[ j + 1 ] ) - sqr( A[ i + 1 ] );
LL DeltaY2 = F1[ k ] - F1[ j ] + sqr( A[ k + 1 ] ) - sqr( A[ j + 1 ] );
return DeltaX2 * DeltaY1 >= DeltaX1 * DeltaY2;
}
void Work() {
Clear();
scanf( "%lld%lld", &N, &M );
for( LL i = 1; i <= N; ++i ) scanf( "%lld", &A[ i ] );
sort( A + 1, A + N + 1, less< LL >() );
for( LL i = 1; i <= N; ++i ) F1[ i ] = sqr( A[ i ] - A[ 1 ] );
for( LL j = 2; j <= M; ++j ) {
Clear2();
Queue[ R++ ] = j - 1;
for( LL i = j; i <= N; ++i ) {
while( L + 1 < R && Less( Queue[ L ], Queue[ L + 1 ], A[ i ] ) )
++L;
F2[ i ] = F1[ Queue[ L ] ] + sqr( A[ i ] - A[ Queue[ L ] + 1 ] );
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 ] );
return;
}
int main() {
LL t; scanf( "%lld", &t );
for( LL i = 1; i <= t; ++i ) {
printf( "Case %lld: ", i );
Work();
}
return 0;
}
HDU 3480 Division DP斜率优化的更多相关文章
- HDU 3480 Division(斜率优化+二维DP)
Division Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 999999/400000 K (Java/Others) Tota ...
- HDU 3480 Division(斜率DP裸题)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3480 题目大意:将n个数字分成m段,每段价值为(该段最大值-该段最小值)^2,求最小的总价值. 解题思 ...
- HDU 2829 [Lawrence] DP斜率优化
解题思路 首先肯定是考虑如何快速求出一段铁路的价值. \[ \sum_{i=1}^k \sum_{j=1, j\neq i}^kA[i]A[j]=(\sum_{i=1}^kA[i])^2-\sum_{ ...
- HDU.2829.Lawrence(DP 斜率优化)
题目链接 \(Description\) 给定一个\(n\)个数的序列,最多将序列分为\(m+1\)段,每段的价值是这段中所有数两两相乘的和.求最小总价值. \(Solution\) 写到这突然懒得写 ...
- hdu 3480 Division(四边形不等式优化)
Problem Description Little D is really interested in the theorem of sets recently. There’s a problem ...
- hdu 3480 Division(斜率优化DP)
题目链接:hdu 3480 Division 题意: 给你一个有n个数的集合S,现在让你选出m个子集合,使这m个子集合并起来为S,并且每个集合的(max-min)2 之和要最小. 题解: 运用贪心的思 ...
- HDU 3507 [Print Article]DP斜率优化
题目大意 给定一个长度为\(n(n \leqslant 500000)\)的数列,将其分割为连续的若干份,使得 $ \sum ((\sum_{i=j}^kC_i) +M) $ 最小.其中\(C_i\) ...
- HDU 3507 单调队列 斜率优化
斜率优化的模板题 给出n个数以及M,你可以将这些数划分成几个区间,每个区间的值是里面数的和的平方+M,问所有区间值总和最小是多少. 如果不考虑平方,那么我们显然可以使用队列维护单调性,优化DP的线性方 ...
- 【BZOJ-4518】征途 DP + 斜率优化
4518: [Sdoi2016]征途 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 230 Solved: 156[Submit][Status][ ...
随机推荐
- Codeforces 1228D. Complete Tripartite
传送门 不妨设 $1$ 号点在集合 $1$ 里 那么对于其他点,有且只有所有和 $1$ 没有边的点都在集合 $1$ 里 考虑不在集合 $1$ 的任意一个点 $x$ ,不妨设它在集合 $2$ 里 那么所 ...
- VMware中centos7访问外网配置
1.配置虚拟机网络适配器,选择NAT模式 2.在编辑->虚拟机网络编辑器->更改设置 选择目前使用的网卡 3.通过ifconfig查看网卡配置 4.编辑网络配置对应上面网卡名称ens33 ...
- 教你用python爬取网站美女图(附代码及教程)
我前几篇文章都是说一些python爬虫库的用法,还没有说怎样利用好这些知识玩一些好玩的东西.那我今天带大家玩好玩又刺激的,嘻嘻!对了,requests库和正则表达式很重要的,一定要学会!一定要学会!! ...
- 【版本控制工具】 Git进阶1
一.Git常用命令 Git中的很多命令与Linux相同(比如修改,查询,编辑,移动等),这里可以参考我之前的一篇文章https://www.cnblogs.com/ywb-articles/p/105 ...
- (转)FPS游戏服务器设计的问题
FPS游戏服务器设计的问题出处:http://www.byteedu.com/thread-20-1-1.html一.追溯 去gameloft笔试,有一个题目是说: 叫你去设计一个FPS(第一人称射击 ...
- matplotlib:python数据处理三剑客之一
1.基本使用 import numpy as np import matplotlib.pyplot as plt import pandas as pd # 生成一系列x x = np.linspa ...
- 修改mysql的binlog的位置
最近项目上装的mysql服务,分配的磁盘空间太小了,导致binlog两天时间就能打满,这里记录下处理方式 mysql的binlog日志是一个很重要的日志,以事件形式记录了所有的DDL和DML(除了数据 ...
- 单节点oracle、ASM 详细安装步骤
目录 1.安装环境 2.系统要求 2.1 Linux安装Oracle系统要求 1.查看RAM和交换空间以及磁盘大小 2.检查所需软件包 3.配置host和主机名 2.2修改操作系统核心参数 1.创建相 ...
- ES添加文档 踩坑之 —— The number of object passed must be even but was [1]
读取文件,获取json格式的数据doc, 然后使用 bulkRequestBuilder.add(client.prepareIndex(index, type, id).setSource(doc) ...
- 提高docker加载速度
由于国情,我们需要对配置一下docker的下载镜像,提高一下后续的加载速度. 使用vim编辑 /etc/docker/daemon.json, 增加如下内容. { "registry-mir ...