题目描述

现在有一个长度为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 贪心的更多相关文章

  1. 【51Nod】1510 最小化序列 贪心+动态规划

    [题目]1510 最小化序列 [题意]给定长度为n的数组A和数字k,要求重排列数组从而最小化: \[ans=\sum_{i=1}^{n-k}|A_i-A_{i+k}|\] 输出最小的ans,\(n \ ...

  2. UVA 714 Copying Books 最大值最小化问题 (贪心 + 二分)

      Copying Books  Before the invention of book-printing, it was very hard to make a copy of a book. A ...

  3. 【BZOJ-1046】上升序列 DP + 贪心

    1046: [HAOI2007]上升序列 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 3723  Solved: 1271[Submit][Stat ...

  4. luogu P5470 [NOI2019]序列 dp 贪心 费用流 模拟费用流

    LINK:序列 考虑前20分 容易想到爆搜. 考虑dp 容易设\(f_{i,j,k,l}\)表示前i个位置 选了j对 且此时A选择了k个 B选择了l个的最大值.期望得分28. code //#incl ...

  5. 最大值最小化(DP)

    题目来源:网易有道2013年校园招聘面试一面试题 题目描述: 在印刷术发明之前,复制一本书是一个很困难的工作,工作量很大,而且需要大家的积极配合来抄写一本书,团队合作能力很重要.当时都是通过招募抄写员 ...

  6. 51nod 1065 最小正子段和 (贪心)

    题目:传送门. 题意:中文题. 题解:求前缀和,并且标记每个数的下标,按照前缀和大小进行从小到大排序.随后进行遍历,如果满足下标data[i-1].id<data[i].id&& ...

  7. [BZOJ1046][HAOI2007]上升序列 DP+贪心

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1046 我们先求出对于每一个数字作为开头的LCS的长度f[i],最长的f[i]为mxlen. ...

  8. UVa 714 Copying books 贪心+二分 最大值最小化

    题目大意: 要抄N本书,编号为1,2,3...N, 每本书有1<=x<=10000000页, 把这些书分配给K个抄写员,要求分配给某个抄写员的那些书的编号必须是连续的.每个抄写员的速度是相 ...

  9. POJ3273-Monthly Expense (最小化最大值)

    题目链接:cid=80117#problem/E">click here~~ [题目大意] 农夫JF在n天中每天的花费,要求把这n天分作m组.每组的天数必定是连续的.要求分得各组的花费 ...

随机推荐

  1. 团队作业9——测试与发布(Beta版本)

    Deadline: 2017-6-5 22:00PM,以博客发表日期为准 评分基准: 按时交 - 有分,检查的项目包括后文的两个方面 测试报告 发布说明 展示博客(单独一篇博客) 晚交 - 0分 迟交 ...

  2. 201521123061 《Java程序设计》第十四周学习总结

    201521123061 <Java程序设计>第十四周学习总结 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据 ...

  3. 201521123073《Java程序设计》第4周学习总结

    一. 本周学习总结 二. 书面作业 1.注释的应用 2.面向对象设计(大作业1,非常重要) 2.1 将在网上商城购物或者在班级博客进行学习这一过程,描述成一个故事.(不得少于50字,参考QQ群中PPT ...

  4. 201521123005 《Java程序设计》 第十周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. 2. 书面作业 本次PTA作业题集异常.多线程 1.finally 题目4-2 1.1 截图你的提交结果(出 ...

  5. 201521123037 《Java程序设计》第11周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多线程相关内容. Java多线程之Executor.ExecutorService.Executors.Callable.Futur ...

  6. 201521123034 《Java程序设计》第9周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前 ...

  7. while循环_do_while循环_switch

    swith语法: switch(值) { case 值1: 语句 break; case 值2: 语句 break; case 值3: 语句 break; default: break; } 1.值与 ...

  8. Redis总结(六)Redis配置文件全解

    前面已经写了一些关于redis 的介绍,redis 的基本功能和用法,基本上都说了,有问题的可以去看看 http://www.cnblogs.com/zhangweizhong/category/77 ...

  9. SpringMVC第七篇【RESTful支持、拦截器】

    RESTful支持 我们在学习webservice的时候可能就听过RESTful这么一个名词,当时候与SOAP进行对比的-那么RESTful究竟是什么东东呢??? RESTful(Representa ...

  10. 【转】MySQL分库分表环境下全局ID生成方案

    转载一篇博客,里面有很多的知识和思想值得我们去思考. —————————————————————————————————————————————————————————————————————— 在大 ...