poj1160 post office
题目大意:有n个乡村,现在要建立m个邮局,邮局只能建在乡村里。现在要使每个乡村到离它最近的邮局距离的总和尽量小,求这个最小距离和。
n<300,p<30,乡村的位置不超过10000.
分析:这题是IOI的老题了,所以数据规模很小,朴素的DP也可以过。但作为四边形优化的题目也很不错。
设f[i][j]表示前i个乡村设j个邮局的最小距离和。
f[i][j]=min(f[k][j-1]+w(k+1,i)) 其中w(k+1,i)表示第i+1个乡村到第i个乡村到其中位点的距离之和。因为邮局肯定是建立这一段的中位点才能保证这一段的距离和最小。这个是很容易证明的,用反证法即可。
k作为决策点,如果在区间[1,i]中枚举,则总的事件复杂度为O(N^3)
但因为w(k+1,i)满足区间包含关系,同时满足平行四边形关系(证明貌似挺难)。所以f[i][j]也满足平行四边形原理。设s[i][j]表示f[i][j]的最佳决策点,则有
s[i-1][j]<=s[i][j]<=s[i][j+1]。 (1)
但实际上可以从常识角度直接推出上式(1)式。
如果村子数不变,邮局数增加,则邮局的起止范围应该往两边扩张,至少应保持不变;相反,若邮局数减少,则其起止范围应该往中间收缩,至少应保存不变。
所以s[i][j]<=s[i][j+1]。
所以,可以直接应用这个式子1了。
如果邮局数不变,村子数减少(最右边的村子剔除),则邮局应该往左边微调,不可能往右边移动;相反,则邮局应该往右微调。
所以s[i-1][j]<=s[i][j].
w(i,j)有O(1)的方法求出。我们首先预处理出所有乡村到最左边乡村的距离,并求前缀和,记为sum1,;再处理处所有乡村距离最右边的乡村的距离,并求后缀和,记为sum2。
设【i,j】的中位点为k,则w(i,j)=sum1[j]-sum1[k]-(j-k)*(pos[k]-pos[1])+sum2[i]-sum2[k]-(k-i)*(pos[n]-pos[k])
#include<iostream>
#include<cstdio>
#include<cstring>
#define MAXN 305
using namespace std;
int f[MAXN][MAXN],w[MAXN][MAXN],s[MAXN][MAXN],sum1[MAXN],sum2[MAXN];
int pos[MAXN],n,p;
void pre()
{
for(int i=;i<=n;i++)
sum1[i]=sum1[i-]+pos[i]-pos[];
for(int i=n-;i>=;i--)
sum2[i]=sum2[i+]+pos[n]-pos[i];
for(int i=;i<n;i++)
for(int j=i+;j<=n;j++)
{
int k=(i+j)/;
int res=;
res+=sum1[j]-sum1[k]-(j-k)*(pos[k]-pos[]);
res+=sum2[i]-sum2[k]-(k-i)*(pos[n]-pos[k]);
w[i][j]=res;
}
}
int main()
{
scanf("%d%d",&n,&p);
for(int i=;i<=n;i++)
scanf("%d",&pos[i]);
pre();
memset(f,0x5f,sizeof f);
for(int i=;i<=n;i++)
f[i][]=w[][i];
for(int i=;i<=n;i++)
for(int j=min(i,p);j<=n;j++)
{
if(j>=i||j>p)s[i][j]=i;
}
for(int i=;i<=n;i++)
for(int j=min(p,i);j>=;j--)
{
if(i==j){f[i][j]=,s[i][j]=j-;continue;}
for(int k=s[i-][j];k<=s[i][j+];k++)
if(f[i][j]>f[k][j-]+w[k+][i])
{f[i][j]=f[k][j-]+w[k+][i];
s[i][j]=k;
}
}
printf("%d\n",f[n][p]);
}
poj1160 post office的更多相关文章
- POJ1160 Post Office[序列DP]
Post Office Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 18680 Accepted: 10075 Des ...
- POJ1160 Post Office (四边形不等式优化DP)
There is a straight highway with villages alongside the highway. The highway is represented as an in ...
- POJ-1160 Post Office (DP+四边形不等式优化)
题目大意:有v个村庄成直线排列,要建设p个邮局,为了使每一个村庄到离它最近的邮局的距离之和最小,应该怎样分配邮局的建设,输出最小距离和. 题目分析:定义状态dp(i,j)表示建设 i 个邮局最远覆盖到 ...
- [IOI2000][POJ1160]Post office
题面在这里 题意 一条路上有\(n\)个村庄,坐标分别为\(x[i]\),你需要在村庄上建设\(m\)个邮局,使得 每个村庄和最近的邮局之间的所有距离总和最小,求这个最小值. 数据范围 \(1\le ...
- [POJ1160] Post Office [四边形不等式dp]
题面: 传送门 思路: dp方程实际上很好想 设$dp\left[i\right]\left[j\right]$表示前$j$个镇子设立$i$个邮局的最小花费 然后状态转移: $dp\left[i\ri ...
- DP---基本思想 具体实现 经典题目 POJ1160 POJ1037
POJ1160, post office.动态规划的经典题目.呃,又是经典题目,DP部分的经典题目怎就这么多.木有办法,事实就这样. 求:在村庄内建邮局,要使村庄到邮局的距离和最小. 设有m个村庄,分 ...
- HDU3480 Division——四边形不等式或斜率优化
题目大意 将N个数分成M部分,使每部分的最大值与最小值平方差的和最小. 思路 首先肯定要将数列排序,每部分一定是取连续的一段,于是就有了方程 $\Large f(i,j)=min(f(i-1,k-1) ...
- IOI2000 Post Office (POJ1160)
前言 昨天XY讲课!讲到这题!还是IOI的题!不过据说00年的时候DP还不流行. 题面 http://poj.org/problem?id=1160 分析 § 1 中位数 首先我们考虑,若有x1 & ...
- 【poj1160】 Post Office
http://poj.org/problem?id=1160 (题目链接) 题意 按照递增顺序给出一条直线上坐标互不相同的n个村庄,要求从中选择p个村庄建立邮局,每个村庄使用离它最近的那个邮局,使得所 ...
随机推荐
- live555源代码编译
参考http://www.cnblogs.com/MikeZhang/archive/2013/04/24/live555Windows_20130424.html 环境:windowsxp + VS ...
- 关于sql where id in 转换成数据类型 int 时失败(转)
有执行sql条件语句where id in(@参数)的时候,如果处理不当,就会出现问题:如下面这个存储过程: alter proc Web_gettwtwgoldgameserverGoldSell@ ...
- HDU 1024 Max Sum Plus Plus --- dp+滚动数组
HDU 1024 题目大意:给定m和n以及n个数,求n个数的m个连续子系列的最大值,要求子序列不想交. 解题思路:<1>动态规划,定义状态dp[i][j]表示序列前j个数的i段子序列的值, ...
- 第3章 rpm命令管理
3-1 RPM包命名规则 3-2 安装命令 3-3 升级与卸载 3-4 RPM包查询 3-5 RPM包校验
- Android应用开发高效工具集1---ant构建简单Android项目
本文转载于:http://blog.csdn.net/lincyang/article/details/40950153 在java编译那些事儿中提到了用ant去编译Java项目,今天扩展到用它来构建 ...
- GitHub windows客户端拉代码和提交代码
1,拉别人的代码, 比如https://github.com/greenrobot/EventBus 这个库,先用浏览器访问,然后git账号登陆,点击fock到自己的库里 点击Fork 然后打开Git ...
- js里的原型
<script type="text/javascript"> function People(name){ this.name = name; //对象方法 this ...
- System.Diagnostics命名空间里的Debug类和Trace类的用途
在 .NET 类库中有一个 System.Diagnostics 命名空间,该命名空间提供了一些与系统进程.事件日志.和性能计数器进行交互的类库.当中包括了两个对开发人员而言十分有用的类--Debug ...
- call和apply的差别
Call(thisArg,arg1,arg2,-..) apply(thisArg,[arg1,arg2-.])
- N天前涨停过的票
zd(0,300,10)B2:=REF(C,1)*1.1-C;B3:BARSLAST(B2<0.01)=ZD01;{n天前涨停股票}