Description

There is a straight highway with villages alongside the highway. The highway is represented as an integer axis, and the position of each village is identified with a single integer coordinate. There are no two villages in the same position. The distance between two positions is the absolute value of the difference of their integer coordinates.

Post offices will be built in some, but not necessarily all of the villages. A village and the post office in it have the same position. For building the post offices, their positions should be chosen so that the total sum of all distances between each village and its nearest post office is minimum.

You are to write a program which, given the positions of the villages and the number of post offices, computes the least possible sum of all distances between each village and its nearest post office.

Input

Your program is to read from standard input. The first line contains two integers: the first is the number of villages V, 1 <= V <= 300, and the second is the number of post offices P, 1 <= P <= 30, P <= V. The second line contains V integers in increasing order. These V integers are the positions of the villages. For each position X it holds that 1 <= X <= 10000.

Output

The first line contains one integer S, which is the sum of all distances between each village and its nearest post office.

Sample Input

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

Sample Output

9

思路:

1. dist[i][j] 表示在村子 i, j 之间选一点建邮局并使得 i,j 之间的所有村子到该邮局的距离之和最小. 选择方法是固定的, 总是选择 i,j 最中间的那个村子, mid = (i+j+1)/2

2. dp[i][j] 表示前 i 个村子建立 j 个邮局后各个村子到邮局的总距离之和的最小值

3. dp[i][j] = dp[k][j-1] + dist[k+1][i], 类似背包, 不过这里有个枚举的过程.

为什么第 k+1 个村庄非得去 (k+1,j) 之间的那个邮局, 这应该是个枚举的过程, 强制 0~j-1 分配 k 个, j~i 分配 1 个, 枚举所有可能性

总结:

1. 四边形不等式: 状态转移方程形如:f[i] = opt{f[j]+w[j , i]}  其中b[i] <= j <= i-1, 同时满足w[i , j] + w[i' , j'] <= w[i , j'] + w[i' , j], 其中 i <= i' <= j' <= j, 则能够使用四边形优化, 减少 k 的枚举量, 加速状态转移

代码:

#include <iostream>
using namespace std;
const int MAXN = 310;
int village[MAXN];
int dist[MAXN][MAXN];
int dp[MAXN][40];
int V, P, S; void preProcess() { for(int i = 1; i <= V; i ++) {
for(int j = i; j <= V; j ++) {
int mid = (i+j+1)>>1;
int sum = 0;
for(int k = i; k <= j; k ++) {
sum += abs(village[mid]-village[k]);
}
dist[i][j] = sum;
}
}
int INF = 0X3f;
memset(dp, INF, sizeof(dp));
dp[0][0] = 0; } // dp[i][j] = min(dp[k][j-1] + dist[k+1][j])
int mainFunc() {
for(int i = 1; i <= V; i ++) {
for(int j = 1; j <= P; j ++) {
for(int k = 0; k < i; k ++) {
dp[i][j] = min(dp[i][j], dp[k][j-1] + dist[k+1][i]);
}
}
} return dp[V][P];
}
int main() {
freopen("E:\\Copy\\ACM\\poj\\1160\\in.txt", "r", stdin);
while(cin>> V >> P) {
for(int i = 1; i <= V; i ++) {
scanf("%d", &village[i]);
}
preProcess(); cout << mainFunc() << endl;
}
return 0;
}

  

POJ 1160 Post Office(区间DP)的更多相关文章

  1. POJ 1160 Post Office(DP+经典预处理)

    题目链接:http://poj.org/problem?id=1160 题目大意:在v个村庄中建立p个邮局,求所有村庄到它最近的邮局的距离和,村庄在一条直线上,邮局建在村庄上. 解题思路:设dp[i] ...

  2. poj 1160 Post Office (间隔DP)

    Post Office Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 15966   Accepted: 8671 Desc ...

  3. POJ - 3280Cheapest Palindrome-经典区间DP

    POJ - 3280 Cheapest Palindrome Time Limit: 2000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & ...

  4. poj 2955 括号匹配 区间dp

    Brackets Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6033   Accepted: 3220 Descript ...

  5. POJ 3280 Cheapest Palindrome (区间DP) 经典

    <题目链接> 题目大意: 一个由小写字母组成的字符串,给出字符的种类,以及字符串的长度,再给出添加每个字符和删除每个字符的代价,问你要使这个字符串变成回文串的最小代价. 解题分析: 一道区 ...

  6. POJ 1141 Brackets Sequence(区间DP, DP打印路径)

    Description We give the following inductive definition of a “regular brackets” sequence: the empty s ...

  7. POJ 2176 Folding(区间DP)

    题意:给你一个字符串,请把字符串压缩的尽量短,并且输出最短的方案. 例如:AAAAA可压缩为5(A), NEERCYESYESYESNEERCYESYESYES可压缩为2(NEERC3(YES)). ...

  8. POJ 2955 Brackets (区间DP,常规)

    题意: 给出一个字符串,其中仅仅含 “ ( ) [ ] ” 这4钟符号,问最长的合法符号序列有多长?(必须合法的配对,不能混搭) 思路: 区间DP的常规问题吧,还是枚举区间[i->j]再枚举其中 ...

  9. POJ - 2955 Brackets (区间DP)

    题目: 给出一个有括号的字符串,问这个字符串中能匹配的最长的子串的长度. 思路: 区间DP,首先枚举区间长度,然后在每一个长度中通过枚举这个区间的分割点来更新这个区间的最优解.还是做的少. 代码: / ...

随机推荐

  1. qt 例子地址

    http://blog.sina.com.cn/s/articlelist_2801495241_0_2.html qt打包http://blog.chinaunix.net/uid-24641004 ...

  2. LeetCode: Regular Expression Matching 解题报告

    Roman to IntegerGiven a roman numeral, convert it to an integer. Input is guaranteed to be within th ...

  3. 在linux命令行输出颜色

    示例: #include <stdio.h> int main() { printf("\e[31;1m Hello, world! \e[0m\n"); } 也就是说 ...

  4. pyqt重写键盘事件+获取信号发送对象

    # _*_ coding:utf-8 _*_ import sys from PyQt4 import QtGui,QtCore class Example(QtGui.QMainWindow): d ...

  5. Elastic-Job - 分布式定时任务框架

    Elastic-Job - 分布式定时任务框架 摘要 Elastic-Job是ddframe中dd-job的作业模块中分离出来的分布式弹性作业框架.去掉了和dd-job中的监控和ddframe接入规范 ...

  6. 使用平台调用(P/Invoke)

    使用平台调用 P/Invoke.它的全名叫平台调用(platform invoke).用于调用dll 中实现的非托管的单调(flat)编程接口.被称为使用C或C++ 调用约定(calling conv ...

  7. iOS边练边学--自定义等高的cell

    一.storyboard自定义cell <1>创建一个继承自UITableViewCell的子类,比如ChaosDealCell <2>在storyboard中 <2.1 ...

  8. 关闭 禁用 Redis危险命令

    Redis的危险命令主要有: flushdb,清空数据库 flushall,清空所有记录,数据库 config,客户端连接后可配置服务器 keys,客户端连接后可查看所有存在的键 我们常常需要禁用以上 ...

  9. 更改HDFS权限

    hdfs dfs -chmod -R 755 / 之前执行过这条语句,但是总是提示: 15/05/21 08:10:18 WARN util.NativeCodeLoader: Unable to l ...

  10. android tab之间滑动切换界面功能

    1. onTouchListener();                       //捕捉touch事件,比如说onDown 需要将可滑动的控件加上两个方法:(1)view.setOnTouch ...