邮局加强版:四边形不等式优化DP
题目描述
一些村庄建在一条笔直的高速公路边上,我们用一条坐标轴来描述这条公路,每个村庄的坐标都是整数,没有两个村庄的坐标相同。两个村庄的距离定义为坐标之差的绝对值。我们需要在某些村庄建立邮局。使每个村庄使用与它距离最近的邮局,建立邮局的原则是:所有村庄到各自使用的邮局的距离总和最小。数据规模:1<=村庄数<=1600, 1<=邮局数<=200, 1<=村庄坐标<=maxlongint
输入
2行第一行:n m {表示有n个村庄,建立m个邮局} 第二行:a1 a2 a3 .. an {表示n个村庄的坐标}
输出
1行第一行:l 个整数{表示最小距离总和}
样例输入
10 5
1 2 3 6 7 9 11 22 44 50
样例输出
9
这道题目是IOI2000的真题哦~
可以这样考虑:
给定一个区间,假设我们要建一个邮局,那么一定是在这个序列的中点,所以我们可以先预处理出序列区间[i,j]之间的距离
一个邮局的最短距离记录为sum[i][j],然后用f[i][j]表示到i个村庄建立j个邮局的最短距离和,那么就有状态转移方程:
f[i][j]=min(f[i][j],f[k][j-1]+sum[k+1][i]);
这样,代码就好写了。
但是——这个数据,用O(n3) 的普通DP算法显然无法通过。
O(n3)代码如下:
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[];
long long sum[]];
long long f[][];
//f[i][j]表示前i个村庄设j个邮局
//sum[i][j]表示在第i个村庄到第j个村庄设一个邮局的路程
int main(void){
cin>>n>>m;
for (int i=;i<=n;i++) cin>>a[i];
sort(a+,a+n+);
for (int i=;i<=n;i++){
for (int j=i;j<=n;j++){
sum[i][j]=dis(i,j);
}
}
memset(f,0x3f,sizeof(f));
for (int i=;i<=n;i++){
f[i][]=sum[][i];
}
for (int i=;i<=n;i++){
for (int j=;j<=min(i,m);j++){
for (int k=j-;k<=i-;k++){
f[i][j]=min(f[i][j],f[k][j-]+sum[k+][i]);
}
}
}
cout<<f[n][m]<<endl;
}
这东西肯定过不了啊~
那怎么办?"四边形不等式!"
f[a][c]+f[b][d]<=f[b][c]+f[a][d]
( a < b <= c< d )
(可以理解成:交叉小于包含)
满足这个条件的DP方程(或者说是别的什么数组啊之类的)就称为***为凸。
(以下一段文字来自https://blog.csdn.net/noiau/article/details/72514812)
给出两个定理:
1、如果上述的w函数同时满足区间包含单调性和四边形不等式性质,那么函数dp也满足四边形不等式性质
我们再定义s(i,j)表示 dp(i,j) 取得最优值时对应的下标(即 i≤k≤j 时,k 处的 dp 值最大,则 s(i,j)=k此时有如下定理
2、假如dp(i,j)满足四边形不等式,那么s(i,j)单调,即 s(i,j)≤s(i,j+1)≤s(i+1,j+1)
大家可以自己尝试推倒一下,为什么f[i][j]和sum[i][j]是满足这个式子的(因为我懒得再推了)
再就是要证明"决策单调"
(以下一段文字来自https://blog.csdn.net/noiau/article/details/72514812)
如果我们用s[i][j]表示dp[i][j]取得最优解的时候k的位置的话
那么我们要证明如下结论的成立性:
s[i][j-1]<=s[i][j]<=s[i+1][j]
对于s[i][j-1]<=s[i][j]来说,我们先令dp[i][j-1]取得最优解的时候的k值为y,然后令除了最优值以外的其他值可以为x,这里我们由于要讨论单调性,所以让x小于y,即x<=y<=j-1< j
这里的证明更为繁琐,在实际应用中,我们可以写出O(n3)后,自己跑一边是否决策单调,不是就输出"false"就行了。
在这道题中,我们要注意三点:
- s数组(决策数组)的初始化
- 循环的次序
- 对邮局多于村庄的特判(血泪)
话不多说,代码上
#include<bits/stdc++.h>
using namespace std;
int n,m;
int a[];
long long sum[][];
long long f[][];
int s[][];
//s是决策数组
int main(void){
cin>>n>>m;
if(m>=n){
printf("");
return ;
}
for (int i=;i<=n;i++) cin>>a[i];
sort(a+,a+n+);
for (int i=;i<=n;i++){
sum[i][i]=;
for (int j=i+;j<=n;j++){
sum[i][j]=sum[i][j-]+a[j]-a[(i+j)/];
}
}
memset(f,0x3f,sizeof(f));
//注意这里f要初始化成最大值
memset(s,,sizeof(s));
for (int i=;i<=n;i++){
f[i][]=sum[][i];
s[i][]=;
}
for (int j=;j<=m;j++){
s[n+][j]=n;
for (int i=n;i>=j;i--){
for (int k=s[i][j-];k<=s[i+][j];k++){
if (f[k][j-]+sum[k+][i]<f[i][j]){
f[i][j]=f[k][j-]+sum[k+][i];
s[i][j]=k;
}
}
}
}
cout<<f[n][m]<<endl;
}
这样的代码,经过四边形不等式的优化,就是O(n2)的算法了!
(以下一段文字来自https://blog.csdn.net/noiau/article/details/72514812)
关于O(n^2)复杂度的证明
其实证明很简单,对于一个i,j来说,我们要for s[i][j-1]到s[i+1][j]个数,那么所有的i和j加起来一共会for多少次呢?
我们可以这样思考
(s[2][2]-[1][1])+(s[3][3]-s[2][2])+(s[4][4]-s[3][3])+…+(s[n][n]-s[n-1][n-1])=s[n][n]-s[1][1]很显然是小于n的嘛,所以本来是(n *n *n)的复杂度,就这样降成了O(n *n)啦
(关于四边形不等式强推https://blog.csdn.net/noiau/article/details/72514812这篇博客)
FFFeiya编辑于2018.7.30
邮局加强版:四边形不等式优化DP的更多相关文章
- hdu 2829 Lawrence(四边形不等式优化dp)
T. E. Lawrence was a controversial figure during World War I. He was a British officer who served in ...
- BZOJ1563/洛谷P1912 诗人小G 【四边形不等式优化dp】
题目链接 洛谷P1912[原题,需输出方案] BZOJ1563[无SPJ,只需输出结果] 题解 四边形不等式 什么是四边形不等式? 一个定义域在整数上的函数\(val(i,j)\),满足对\(\for ...
- 【转】斜率优化DP和四边形不等式优化DP整理
(自己的理解:首先考虑单调队列,不行时考虑斜率,再不行就考虑不等式什么的东西) 当dp的状态转移方程dp[i]的状态i需要从前面(0~i-1)个状态找出最优子决策做转移时 我们常常需要双重循环 (一重 ...
- codevs3002石子归并3(四边形不等式优化dp)
3002 石子归并 3 参考 http://it.dgzx.net/drkt/oszt/zltk/yxlw/dongtai3.htm 时间限制: 1 s 空间限制: 256000 KB 题目等级 ...
- CF321E Ciel and Gondolas Wqs二分 四边形不等式优化dp 决策单调性
LINK:CF321E Ciel and Gondolas 很少遇到这么有意思的题目了.虽然很套路.. 容易想到dp \(f_{i,j}\)表示前i段分了j段的最小值 转移需要维护一个\(cost(i ...
- HDU 2829 Lawrence (斜率优化DP或四边形不等式优化DP)
题意:给定 n 个数,要你将其分成m + 1组,要求每组数必须是连续的而且要求得到的价值最小.一组数的价值定义为该组内任意两个数乘积之和,如果某组中仅有一个数,那么该组数的价值为0. 析:DP状态方程 ...
- 四边形不等式优化DP——石子合并问题 学习笔记
好方啊马上就要区域赛了连DP都不会QAQ 毛子青<动态规划算法的优化技巧>论文里面提到了一类问题:石子合并. n堆石子.现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆石子合并成新的 ...
- POJ 1160 四边形不等式优化DP Post Office
d(i, j)表示用i个邮局覆盖前j个村庄所需的最小花费 则有状态转移方程:d(i, j) = min{ d(i-1, k) + w(k+1, j) } 其中w(i, j)的值是可以预处理出来的. 下 ...
- POJ 1160 Post Office (四边形不等式优化DP)
题意: 给出m个村庄及其距离,给出n个邮局,要求怎么建n个邮局使代价最小. 析:一般的状态方程很容易写出,dp[i][j] = min{dp[i-1][k] + w[k+1][j]},表示前 j 个村 ...
随机推荐
- 微信小程序详细图文教程-10分钟完成微信小程序开发部署发布
很多朋友都认为微信小程序申请.部署.发布很难,需要很长时间. 实际上,微信和腾讯云同是腾讯产品,已经提供了10分钟(根据准备资源情况,已完成小程序申请认证)完成小程序开发.部署.发布的方式.当然,实现 ...
- MQ单一消息完整流程
public class QueueManger { private static string QueuePath = @".\private$\{0}"; /// <su ...
- [日常] Linux下vim的常用命令总结
vim按d表示剪切按dd剪切一行vim命令:命令模式 /关键字 n继续向下查找 vim的多行注释:1.按ctrl + v进入 visual block模式2.按上下选中要注释的行3.按大写字母I,再插 ...
- Mybatis插件开发
前面几篇文章介绍了Mybtis中四个重要的对象,其中提到它们都是在Configuration中被创建的,我们一起看一下创建四大对象的方法,代码如下所示: public ParameterHandler ...
- BZOJ4806(SummerTrainingDay03-K dp)
炮 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 464 Solved: 243[Submit][Status][Discuss] Descript ...
- python学习之老男孩python全栈第九期_day002作业
1. 判断下列逻辑语句的True,False.(1) 1 > 1 or 3 < 4 or 4 > 5 and 2 > 1 and 9 > 8 or 7 < 6Tru ...
- linux学习笔记-目录结构(1)
每个linux系统的目录结构差不多,因为有FHS(Filesystem Hierarchy Standard)标准的规范. FHS的重点在于规范每个特定的目录下应该要放什么样的数据. FHS依据文件系 ...
- Bootstrap4响应式布局之栅格系统
前面说了Bootstrap4的下载和简单使用,现在我们接着往下学习,Bootstrap4的响应式布局主要依靠栅格系统来实现的.面老K先来讲解一下Bootstrap4的栅格系统,让你能够更快的了解Boo ...
- 【代码笔记】iOS-只让textField使用键盘通知
代码: #import "ViewController.h" @interface ViewController () @end @implementation ViewContr ...
- svn本地连接服务器失败,但是浏览器可以
tortoise svn无法连接到服务器,清空“Autherticate data”后,再进行更新,提交,log查看等操作,svn还是不提示输入用户名和密码,而是报: error: Unable to ...