51nod 1510 最小化序列 | DP 贪心
题目描述
现在有一个长度为n的数组A,另外还有一个整数k。数组下标从1开始。
现在你需要把数组的顺序重新排列一下使得下面这个的式子的值尽可能小。
∑|A[i]−A[i+k]|
特别的,你也可以不对数组进行重新排列。
Input
单组测试数据。
第一行包含两个整数n,k (2≤n≤3*10^5, 1≤k≤min(5000,n-1))。
第二行包含n个整数 A[1],A[2],...,A[n] (-10^9≤A[i]≤10^9)。
Output
输出答案占一行。
Input示例
3 2
1 2 4
Output示例
1
题解
这道题相当于把所有数分成了互不关联的k组,由于n不一定是k的倍数,其中一些组有 n / k + 1个元素,另一些有 n / k 个元素。
在每一组中,为了使“相邻元素的差的绝对值之和”最小,将元素从小到大排序,则这一组的“相邻元素的差的绝对值之和”就是最大元素-最小元素。那么只要使每一组的最大值-最小值最小就好了。
很容易想到把整个数组排好序后,直接取前n/k + 1组为第一组,取下面n/k + 1组为第二组……在n是k的倍数时这很好,可一个问题是:有些组有n/k个元素,有些有n/k+1个元素,令哪些组为前者,哪些为后者呢?这会影响最终的答案。
发现两种“组”的数目是固定的,并且都小于等于5000,那么我们结合dp:
dp[i][j]表示n/k + 1个元素的组已经选了i个,n/k个元素的组已经选了j个,能得到的最小分数。
dp[i][j] 可以从 dp[i - 1][j] 和 dp[i][j - 1]两个转移。
设排序后的序列为a[i], p1表示dp[i - 1][j]在排序后的序列中一共用完了前多少个元素,p2表示dp[i][j - 1]在排序后的序列中一共用完了前多少个元素。
那么可以写出状态转移方程:
dp[i][j] = min(dp[i - 1][j] + a[p1 + (n/k + 1)] - a[p1 + k], dp[i][j - 1] + a[p2 + n/k] - a[p2])
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define space putchar(' ')
#define enter putchar('\n')
template <class T>
bool read(T &x){
char c;
bool minus = ;
while(c = getchar(), c < '' || c > '')
if(c == '-') minus = ;
else if(c == EOF) return ;
x = c - '';
while(c = getchar(), c >= '' && c <= '')
x = x * + c - '';
if(minus) x = -x;
return ;
}
template <class T>
void write(T x){
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar('' + x % );
} const int N = , M = ;
int n, k, l1, l2, t1, t2, a[N], dp[M][M]; int main(){ read(n), read(k);
for(int i = ; i <= n; i++)
read(a[i]);
sort(a + , a + n + );
l1 = n/k + , l2 = n/k;
t1 = n % k, t2 = k - t1;
for(int i = , p = ; i <= t1; i++)
dp[i][] = dp[i - ][] + a[p + l1] - a[p + ], p += l1;
for(int j = , p = ; j <= t2; j++)
dp[][j] = dp[][j - ] + a[p + l2] - a[p + ], p += l2;
for(int i = , p1, p2; i <= t1; i++)
for(int j = ; j <= t2; j++){
p1 = (i - ) * l1 + j * l2;
p2 = i * l1 + (j - ) * l2;
dp[i][j] = min(dp[i - ][j] + a[p1 + l1] - a[p1 + ],
dp[i][j - ] + a[p2 + l2] - a[p2 + ]);
}
write(dp[t1][t2]), enter; return ;
}
51nod 1510 最小化序列 | DP 贪心的更多相关文章
- 【51Nod】1510 最小化序列 贪心+动态规划
[题目]1510 最小化序列 [题意]给定长度为n的数组A和数字k,要求重排列数组从而最小化: \[ans=\sum_{i=1}^{n-k}|A_i-A_{i+k}|\] 输出最小的ans,\(n \ ...
- UVA 714 Copying Books 最大值最小化问题 (贪心 + 二分)
Copying Books Before the invention of book-printing, it was very hard to make a copy of a book. A ...
- 【BZOJ-1046】上升序列 DP + 贪心
1046: [HAOI2007]上升序列 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3723 Solved: 1271[Submit][Stat ...
- luogu P5470 [NOI2019]序列 dp 贪心 费用流 模拟费用流
LINK:序列 考虑前20分 容易想到爆搜. 考虑dp 容易设\(f_{i,j,k,l}\)表示前i个位置 选了j对 且此时A选择了k个 B选择了l个的最大值.期望得分28. code //#incl ...
- 最大值最小化(DP)
题目来源:网易有道2013年校园招聘面试一面试题 题目描述: 在印刷术发明之前,复制一本书是一个很困难的工作,工作量很大,而且需要大家的积极配合来抄写一本书,团队合作能力很重要.当时都是通过招募抄写员 ...
- 51nod 1065 最小正子段和 (贪心)
题目:传送门. 题意:中文题. 题解:求前缀和,并且标记每个数的下标,按照前缀和大小进行从小到大排序.随后进行遍历,如果满足下标data[i-1].id<data[i].id&& ...
- [BZOJ1046][HAOI2007]上升序列 DP+贪心
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1046 我们先求出对于每一个数字作为开头的LCS的长度f[i],最长的f[i]为mxlen. ...
- UVa 714 Copying books 贪心+二分 最大值最小化
题目大意: 要抄N本书,编号为1,2,3...N, 每本书有1<=x<=10000000页, 把这些书分配给K个抄写员,要求分配给某个抄写员的那些书的编号必须是连续的.每个抄写员的速度是相 ...
- POJ3273-Monthly Expense (最小化最大值)
题目链接:cid=80117#problem/E">click here~~ [题目大意] 农夫JF在n天中每天的花费,要求把这n天分作m组.每组的天数必定是连续的.要求分得各组的花费 ...
随机推荐
- Java 多线程(二) 线程的实现
线程的实现 在Java中通过run方法为线程指明要完成的任务,有两种技术来为线程提供run方法: 1.继承Thread类并重写它的run方法.之后创建这个子类的对象并调用start()方法. 2.通过 ...
- 201521123084 《Java程序设计》第6周学习总结
1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖 ...
- 结对编程1---四则运算---GUI
201421123003 黄建英 201421123004 黄美海 题目描述: 我们在个人作业1中,用各种语言实现了一个命令行的四则运算小程序.进一步,本次要求把这个程序做成GUI(可以是Window ...
- 201521123003《Java程序设计》第6周学习总结
1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 注1:关键词与内容不求多,但概念之间的联系要清晰,内容覆盖 ...
- 201521123079《java程序设计》第5周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 2. 书面作业 1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过? ...
- 201521123070 《JAVA程序设计》第4周学习总结
1. 本章学习总结 1.1 尝试使用思维导图总结有关继承的知识点. http://naotu.baidu.com/file/4de6f42e4f4f6cce0531dd9997b04e60?token ...
- 201521123027 《JAVA程序设计》第3周学习总结
1.本周学习总结 2.书面作业 Q1.代码阅读 public class Test1 { private int i = 1;//这行不能修改 private static int j = 2; pu ...
- 201521123097《Java程序设计》第九周学习总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1.常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己 ...
- arm-linux-gcc 4.3.2编译uboot 1.1.6
在第三期项目的视频中,官方提供了一整套新的工具链,bootloader, 内核和文件系统(arm-linux-gcc_4.3.2, uboot-2012.04.01, linux-3.4.2)其中ub ...
- Chrome控制台选择器简介
Chrome的控制台是支持用$来获取元素的,这点可能是很多人不知道的.本篇文章将会简单介绍怎样更好的来使用这种快捷方式来获取元素. 判断当前窗口的$是来自谁的 我们知道jQ里面经常使用$来进行元素选择 ...