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组.每组的天数必定是连续的.要求分得各组的花费 ...
随机推荐
- 我的hibernate学习记录(一)
之前已经过滤一下hibernate的简单的用法,但是近期有点时间,所以重新看下视频,敲下代码,翻下笔记,写博客与大家分享一下. hibernate简介 Hibernate是一个开放源代码的对象关系映射 ...
- 【Socket编程】Java中网络相关API的应用
Java中网络相关API的应用 一.InetAddress类 InetAddress类用于标识网络上的硬件资源,表示互联网协议(IP)地址. InetAddress类没有构造方法,所以不能直接new出 ...
- win8下安装VC6出现兼容性问题的解决办法
重装系统之后(win8的系统),发现VC6安装出现兼容性问题,花了一些时间解决,有出现的问题都差不多在下面链接的总结中,写的很详细: http://www.docin.com/p-1126120829 ...
- 201521123060 《Java程序设计》第6周学习总结
1. 本周学习总结 1.1 面向对象学习暂告一段落,请使用思维导图,以封装.继承.多态为核心概念画一张思维导图,对面向对象思想进行一个总结. 2. 书面作业 1.clone方法 1.1 Object对 ...
- 201521123110《Java程序设计》第5周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关多态与接口的知识点. 2. 书面作业 1.代码阅读:Child压缩包内源代码 1.1 com.parent包中Child.java文件能否编译通过? ...
- 201521123077 《Java程序设计》第14周学习总结
1. 本周学习总结 1.1以你喜欢的方式(思维导图或其他)归纳总结多数据库相关内容. 2. 书面作业 1. MySQL数据库基本操作 -参考:实验任务书-题目1 建立数据库,将自己的姓名.学号作为一条 ...
- oracle 建表空间->创建用户并把表空间分配给用户->给用户授权->导库
首先注意:我参考网上使用的sysdba模式(normal)登陆的,其他的模式建不了用户(个人没有进行其他模式的表空间尝试,如有人尝试欢迎补充,感激不尽) 表空间相当于表的容器(一下所有的操作都适用于o ...
- Python可视化----------matplotlib.pylot
1 >>> import matplotlib.pyplot as plt 2 >>> plt.axis([0,5,0,20]) 3 [0, 5, 0, 20] 4 ...
- Java内部类的总结
内部类是指在一个外部类的内部再定义一个类.类名不需要和文件夹相同. 内部类分为: 成员内部类.局部内部类.静态嵌套类.匿名内部类 . 1.成员内部类 成员内部类是最普通的内部类,它的定义为位于另一个类 ...
- XML预览
功能: 实现模板文件的预览 模板实体类中有一个content字段,它的值是xml形式的,就是要预览它的内容; 实现思路: 在java后台中将这个xml内容以xml文件的形式保存到服务器上,然后将路 ...