Post Office IOI 2000 /// 区间DP oj24077
题目大意:
给定n个村庄的坐标,两个村庄之间的距离是其坐标之差的绝对值
最多能选m个村庄设立邮局,求设立邮局的地点使得各村庄与邮局距离总和最小
一,
所有的村庄看做在一条直线上
考虑三个因素:i 当前位于第几个村庄,j 已设立邮局的个数,s 村庄与邮局的距离总和
即dp数组为 dp[ i ][ j ] = s , 区间DP,枚举中间点村庄 k
则dp[ i ][ j ]=max{ dp[ k ][ j-1 ] + s( k+1,i ) | 0<k<i}
(1~i村庄设j个邮局) 可由 (1~k村庄设j-1个邮局)+(k+1~i村庄设1个邮局) 得到
二,
再来考虑如何处理s( k,i ),即第 k+1 到 i 村庄之间设立一个邮局的最短距离
即考虑一个区间内选取哪个点可使 其他点到该点的差值的绝对值总和 是最小的
两个点以上的情况 首先可以排除首端和尾端的两个点
奇数个点的情况:
设a<b<c<d<e
1.选取b时
a b c d e
---
---
-------
----------
2.选取c时
a b c d e
------
---
---
------
可看出选取中间点更优
偶数个点的情况:
设a<b<c<d<e<f
1.选取c时
a b c d e f
------
---
---
------
----------
2.选取d时
a b c d e f
---------
------
---
---
------
可看出选取居中的两个点得到的结果是一样的
那么举个例子: s( a,d )=s( a,c )+d到邮局的距离,邮局最佳设立位置为(a+d)/2
就可得到 s( a,d )=s( a,c )+a[ d ]-a[ (a+d)/2 ]
则设数组s[][]保存 两点间设立一个邮局时 区间内村庄与邮局间距离总和的最小值
且 s[ i ][ j ]=s[ i ][ j-1 ] + a[ j ] - a[ (i+j)/2 ]
三,
邮局地点的记录(类似最长上升子序列的路径记录)
利用dp[i][j]的更新过程,枚举中间点k时,若其能更新当前的dp[i][j],
说明 1~i 被分为两个区间 1~k 和 k+1~i,则区间 k+1~i 的邮局设立点为 (i+k+1)/2
那么记录此时前驱为 k,即 pre[i][j]=k,即记录了上一个区间的末尾
则当dp[][]更新结束后,dp[n][m]是1~n村庄设立m个邮局的距离总和最小值
pre[n][m]中记录的是倒数第二个区间的末尾k1,邮局设立点为(n+k1+1)/2
则pre[k1][m-1]中则记录着倒数第三个区间的末尾k2,邮局设立点为(k1+k2+1)/2
则pre[k2][m-2]中则记录着倒数第四个区间的末尾k3 ,......
这样逆推下去 就可以当推到0时 代表已经过了第一个区间
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std; int n,m,a[];
int s[][]; // s[i][j] 在i到j之间设一个邮局的最小距离
int dp[][]; // dp[i][j] 前i个村落设j个邮局的最小花费
int pre[][],ans[]; int main()
{
while(~scanf("%d%d",&n,&m)) { memset(s,,sizeof(s));
memset(dp,INF,sizeof(dp));
memset(pre,,sizeof(pre)); for(int i=;i<=n;i++) scanf("%d",&a[i]);
for(int i=;i<=n;i++) {
for(int j=i+;j<=n;j++)
s[i][j]=s[i][j-]+a[j]-a[(i+j)/];
dp[i][]=s[][i]; // 顺带更新一下1~i设1个邮局的dp[][]
} for(int i=;i<=n;i++) // 枚举末尾
for(int j=;j<=i && j<=m;j++) // 枚举邮局个数
for(int k=j-;k<i;k++) // 枚举 1~i 的中间点
if(dp[k][j-]+s[k+][i]<dp[i][j])
dp[i][j]=dp[k][j-]+s[k+][i], pre[i][j]=k; int x=n,y=m,ind=;
while(x>&&y>) { /// 逆推并将邮局设立位置逆序存入ans[]
ans[ind++]=a[(x+pre[x][y]+)/];
x=pre[x][y--];
} printf("%d\n",dp[n][m]);
while(ind>) { // 从最后一个输出 才是正序
printf("%d ",ans[--ind]);
} printf("\n");
} return ;
}
Post Office IOI 2000 /// 区间DP oj24077的更多相关文章
- [IOI 2000]POJ 1160 Post Office
Post Office Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 22278 Accepted: 12034 Descrip ...
- IOI 98 (POJ 1179)Polygon(区间DP)
很容易想到枚举第一步切掉的边,然后再计算能够产生的最大值. 联想到区间DP,令dp[i][l][r]为第一步切掉第i条边后从第i个顶点起区间[l,r]能够生成的最大值是多少. 但是状态不好转移,因为操 ...
- UVALive 4987---Evacuation Plan(区间DP)
题目链接 https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...
- 2016 ACM/ICPC Asia Regional Shenyang Online 1009/HDU 5900 区间dp
QSC and Master Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others) ...
- poj 3186 Treats for the Cows(区间dp)
Description FJ has purchased N (1 <= N <= 2000) yummy treats for the cows who get money for gi ...
- [poj3280]Cheapest Palindrome_区间dp
Cheapest Palindrome poj-3280 题目大意:给出一个字符串,以及每种字符的加入代价和删除代价,求将这个字符串通过删减元素变成回文字符串的最小代价. 注释:每种字符都是小写英文字 ...
- hdu 4283 区间dp
You Are the One Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)T ...
- POJ1179Polygon(区间dp)
啊~~ 被dp摁在地上摩擦的人 今天做了一道区间dp的题(POJ1179Polygon) 题目: Polygon Time Limit: 1000MS Memory Limit: 10000K T ...
- 区间dp(入门题)
区间dp:顾名思义就是在区间上进行动态规划,通过合并小区间求解一段区间上的最优解. 常见模板: for(int len=1;len<n;len++){//区间长度 for(int be=1;be ...
随机推荐
- Unity 中调用Android的JAVA代码
首先我们要创建一个android项目 因为项目需要使用Unity提供的接口,所以需要将接口classes.jar引入至当前工程但中.接口包的所在地,打开Finder->应用程序->Unit ...
- 【代码工具】Lombok来优雅的编码
前言 Lombok 是一种 Java™ 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO).它通过注解实现这一目的. 正文 添加依赖 在 pom.xml ...
- MLE极大似然估计和EM最大期望算法
机器学习十大算法之一:EM算法.能评得上十大之一,让人听起来觉得挺NB的.什么是NB啊,我们一般说某个人很NB,是因为他能解决一些别人解决不了的问题.神为什么是神,因为神能做很多人做不了的事.那么EM ...
- iBatis开发的一个应用
今天开始学习iBatis框架,感觉这个框架很轻巧,方便,使用上手很快,没有多大的难点,下面就介绍一下第一个应用开发的步骤: 第一步:在mysql的test数据库中建立一张表:account creat ...
- 如何将Canvas中内容保存为图片
Bitmap bm = Bitmap.createBitmap(320, 480, Config.ARGB_8888); Canvas canvas = new Canvas(bm); Paint p ...
- P1831 杠杆数
P1831 杠杆数 题目描述 如果把一个数的某一位当成支点,且左边的数字到这个点的力矩和等于右边的数字到这个点的力矩和,那么这个数就可以被叫成杠杆数. 比如4139就是杠杆数,把3当成支点,我们有这样 ...
- 使用Devstack部署neutron网络节点
本文为minxihou的翻译文章,转载请注明出处Bob Hou: http://blog.csdn.net/minxihou JmilkFan:minxihou的技术博文方向是 算法&Open ...
- (c# )操作Excel的时候出现:不能使用对象或链接
可能就是你打开了多个Excel进程没有关掉出现的问题. 编程:对文件操作的时候要养成关掉进程的习惯 在c#中操作完后关闭资源的代入如下: System.Runtime.InteropServices. ...
- uoj139 【UER #4】被删除的黑白树
题目 不难发现有一个暴力\(dp\) 设\(dp[x][l]\)表示\(x\)点子树内所有叶子节点到\(x\)的路径上都有\(l\)和黑点时最多能染多个黑点 转移就是 \[dp[x][l]=\max( ...
- codeforces round#524 C. Masha and two friends /// 矩形切割
题目大意: 给定n行m列的黑白棋盘如下 给定矩形的左下点x1 y1和右上点x2 y2将这个区域都涂成白色 再给定矩形的左下点x3 y3和右上点x4 y4将这个区域都涂成黑色 求最后棋盘内有分别多少个白 ...