貌似$BZOJ$上并没有这个题。。。

是嫌这个题水了么。。。

还是要氪金权限号???

这里附上洛谷的题面:洛谷P4767 [IOI2000]邮局

题目描述

高速公路旁边有一些村庄。高速公路表示为整数轴,每个村庄的位置用单个整数坐标标识。没有两个在同样地方的村庄。两个位置之间的距离是其整数坐标差的绝对值。

邮局将建在一些,但不一定是所有的村庄中。为了建立邮局,应选择他们建造的位置,使每个村庄与其最近的邮局之间的距离总和最小。

你要编写一个程序,已知村庄的位置和邮局的数量,计算每个村庄和最近的邮局之间所有距离的最小可能的总和。

输入输出格式

输入格式:

第一行包含两个整数:第一个是村庄$V$的数量,第二个是邮局的数量$P$,$1 \leq P \leq 300$,$P \leq V \leq 3000$.

第二行包含$V$个整数。这些整数是村庄的位置。对于每个位置$X$,认为$1 \leq X \leq 10000$。

输出格式:

第一行包含一个整数$S$,它是每个村庄与其最近的邮局之间的所有距离的总和。

输入输出样例

输入样例#1: 复制

10 5
1 2 3 6 7 9 11 22 44 50

输出样例#1: 复制

9

说明

对于40%的数据,$V \leq 300$


题解Here!

首先这是个区间$DP$对吧。

我们一步一步来分析:

首先要将村庄位置排个序,不用多说。

下面开始$DP$。

$No. 1:\text{普通DP}$:

设$dp[i][j]$表示前$i$个村庄中建了$j$个邮局的最优方案。

转移方程长这个样:

$$dp[i][j]=\max\{\ dp[k][j-1]+dis(k+1,i)\ |\ k\in[0,i)\}$$

其中$dis(l,r)$表示在$[l,r]$这个区间内的村庄中建一个邮局对答案的贡献。

利用人类智慧可知把邮局建在中间花费最少。。。

复杂度上限是$O(n^3m)$,实测可以$40\text{分}$。

代码如下:

inline int abs(int x){return x>0?x:-x;}
inline int dis(int l,int r){int mid=(l+r)>>1,s=0;for(int i=l;i<=r;i++)s+=abs(pos[i]-pos[mid]);//pos是村庄位置return s;
}
void work(){dp[0][0]=0;for(int i=1;i<=n;i++)for(int j=1;j<=m&&j<=i;j++)for(int k=0;k<i;k++)dp[i][j]=min(dp[i][j],dp[k][j-1]+dis(k+1,i));printf("%d\n",dp[n][m]);
}

$No. 2:\text{普通DP+优化}$:

我们发现我们的求贡献还要$O(n)$的复杂度,考虑对其进行优化。

我们知道:

$$dis(l,r)=\sum_{i=l}^r|pos_i-pos_{mid}|,mid=\frac{l+r}{2}$$

因为我们的$pos$是有序的,于是:

$$dis(l,r)=\sum_{i=l}^{mid-1}(pos_{mid}-pos_i)+\sum_{i=mid+1}^r(pos_i-pos_{mid}),mid=\frac{l+r}{2}$$

显然拆开:

$$dis(l,r)=(mid-l)pos_{mid}-\sum_{i=l}^{mid-1}pos_i+\sum_{i=mid+1}^rpos_i-(r-mid)pos_{mid},mid=\frac{l+r}{2}$$

合并:

$$dis(l,r)=(2mid-l-r)pos_{mid}+\sum_{i=mid+1}^rpos_i-\sum_{i=l}^{mid-1}pos_i,mid=\frac{l+r}{2}$$

注意,这个地方$2mid-l-r \neq 0$,因为实际算$mid$时,算的其实是$\lfloor\frac{l+r}{2}\rfloor$。

但是这个并不影响复杂度,所以可以保留。

关键是后面那两个$\sum$怎么整?

前缀和!

设$sum(x)=\sum_{i=1}^xpos_i$,则:

$$\left.\begin{array}{}dis(l,r)&=&(2mid-l-r)pos_{mid}+(sum(r)-sum(mid))-(sum(mid-1)-sum(l-1))\\&=&(2mid-l-r)pos_{mid}+sum(l-1)+sum(r)-sum(mid)-sum(mid-1)\end{array}\right.$$

于是预处理前缀和,就可以$O(1)$计算$dis(l,r)$了!

复杂度$O(n^2m)$,实测$60\text{分}$。

代码如下:

inline int dis(int l,int r){int mid=(l+r)>>1;return ((sum[r]-sum[mid])-(sum[mid-1]-sum[l-1])+(mid*2-l-r)*pos[mid]);
}
void work(){dp[0][0]=0;for(int i=1;i<=n;i++)for(int j=1;j<=m&&j<=i;j++)for(int k=0;k<i;k++)dp[i][j]=min(dp[i][j],dp[k][j-1]+dis(k+1,i));printf("%d\n",dp[n][m]);
}

$No. 3:\text{DP+四边形不等式}$:

四边形不等式优化就是:

在$DP$过程中满足:

$$dp[a][c]+dp[b][d]<=dp[a][d]+dp[b][c]$$

并且决策具有单调性。

对于这题,我们发现,$dp[i][j]$的决策只能从$dp[i][j-1],dp[i+1][j]$中选一个进行转移。

于是就可以用四边形不等式优化了!

到此,我们证明了这个题其实是个板子题。。。

记得要倒序$DP$。

附代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define MAXN 3010
using namespace std;
int n,m;
int pos[MAXN],sum[MAXN],from[MAXN][MAXN],dp[MAXN][MAXN];
inline int read(){int date=0,w=1;char c=0;while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}return date*w;
}
inline int dis(int l,int r){int mid=(l+r)>>1;return ((sum[r]-sum[mid])-(sum[mid-1]-sum[l-1])+(mid*2-l-r)*pos[mid]);
}
void work(){for(int j=2;j<=m;j++){from[n+1][j]=n;for(int i=n;i>=1;i--){for(int k=from[i][j-1];k<=from[i+1][j];k++){if(dp[k][j-1]+dis(k+1,i)<dp[i][j]){dp[i][j]=dp[k][j-1]+dis(k+1,i);from[i][j]=k;}}}}printf("%d\n",dp[n][m]);
}
void init(){n=read();m=read();memset(dp,127,sizeof(dp));for(int i=1;i<=n;i++)pos[i]=read();sort(pos+1,pos+n+1);sum[0]=0;for(int i=1;i<=n;i++){sum[i]=sum[i-1]+pos[i];dp[i][1]=dis(1,i);}
}
int main(){init();work();return 0;
}

转载于:https://www.cnblogs.com/Yangrui-Blog/p/9862813.html

BZOJXXXX: [IOI2000]邮局——四边形不等式优化初探相关推荐

  1. Post Office(邮局)之四边形不等式优化dp

    目录 前言 题目 解析 四边形不等式优化 何为四边形不等式 何为区间包含单调性 四边形不等式性质 DP 优化 参考代码(附注释) 前言 可以说这道题我可花费了很大功夫才理解的. 其中有些小技巧也是我钻 ...

  2. [转]四边形不等式优化dp(POJ1160)

    四边形不等式优化动态规划原理: 1.当决策代价函数w[i][j]满足w[i][j]+w[i'][j']<=w[I;][j]+w[i][j'](i<=i'<=j<=j')时,称w ...

  3. 四边形不等式优化 --算法竞赛专题解析(10)

    本系列文章将于2021年整理出版,书名<算法竞赛专题解析>. 前驱教材:<算法竞赛入门到进阶> 清华大学出版社 2019.8 网购:京东 当当      作者签名书 如有建议, ...

  4. 合并石子 四边形不等式优化

    题目描述 有一排石子,共n 堆.现要将石子有次序地合并成一堆.规定每次只能选相邻的2 堆石子合并成新的一堆,并将新的一堆石子数记为该次合并的得分.试设计一个算法,计算出将n堆石子合并成一堆的最小得分. ...

  5. Codevs 3002 石子归并 3(DP四边形不等式优化)

    3002 石子归并 3 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题目描述 Description 有n堆石子排成一列,每堆石子有一个重量w[i], 每次 ...

  6. 四边形不等式优化-石子合并

    四边形不等式优化 四边形不等式定义 在oi历程中,常有如下的dp转移方程 \(f(i,j)=min(f(i,k)+f(k+1,j)+w(i,j))\) \((i<=k<j)\) \(f(i ...

  7. DP 最优二叉树 的四边形不等式优化

    最优比例二叉树.代价函数cost 满足 对任意 a <= b <= c <= d 有 cost[a,c] + cost[b,d] <= cost[a,d] + cost[b,c ...

  8. 【HDU 4905 多校联合】The Little Devil II【DP+四边形不等式优化】

    题意:给出一个数列,每次你可以选择相邻的两个数字进行求GCD,然后得到的数字把这两个数字替代,得到GCD的权值,求最后剩下一个数字后的最大的权值(权值初始是数列的和) 思路:定义dp[i][j]表示区 ...

  9. 【决策单调性分治优化/四边形不等式优化】监狱警卫

    前言 模板一套就AC了... 题目 guardians.cpp 1S/128M 你负责将监狱的警卫指派到最疯狂的罪犯所在的监狱. 一共有N间牢房排列成一行,编号从1~N. 第i间牢房恰好容纳了一个疯狂 ...

最新文章

  1. 几个表示“光”的概念
  2. C# 7中函数多值返回_转自InfoQ
  3. Windows驱动开发 - 设备对象初步学习
  4. Android开发艺术探究Note
  5. python 全局变量与局部变量
  6. 使用layer的弹窗时,出现layer引入成功,触发成功,控制台无报错,但是页面无变化或者仅出现遮罩层的问题的解决思路
  7. 106页的《Python进阶》中文版(附下载)
  8. Python中流程控制-for循环(序列/字典举例)
  9. hdu-2602POJ-3624---01背包裸题
  10. 用MATLAB解决实际数学问题,利用MATLAB解决高等数学问题.doc
  11. JUnit执行单元测试用例成功,mvn test却失败的问题和解决方法
  12. 重复测量方差分析步骤汇总
  13. 计算房贷利率月供相关信息(等额本息)
  14. mongodb安装及操作
  15. 24岁女孩与30多岁成熟有家男人
  16. 360网站卫士cdn全面转向奇安信
  17. 放养型实验室IEEE Access投稿-录用历程
  18. bukgu 论剑 (十年磨一剑,霜刃未曾试。 今日把示君,谁有不平事。)
  19. WIN10怎么让自己桌面看起来好看一点
  20. 火影忍者第1集-日语自学

热门文章

  1. BitmapUtil【缩放bitmap以及将bitmap保存成图片到SD卡中】
  2. 内网网段划分ciso交换机配置
  3. 推荐一个golang的json库
  4. 欢乐暑假-高校俱乐部暑期线上编程竞赛奖励机制
  5. QQ 互联审核不通过问题的解决方法
  6. windows server 2012 RC download.
  7. jquery总结_代码收藏
  8. 10. Firewalls (防火墙 2个)
  9. 闫智宣的开发版_Android
  10. 网络 http服务器-v1-多线程版本