51nod1510 最小序列

Description

现在有一个长度为n的数组A,另外还有一个整数k。数组下标从1开始。

现在你需要把数组的顺序重新排列一下使得下面这个的式子的值尽可能小。

特别的,你也可以不对数组进行重新排列。

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

解题思路:(贪心+DP)

这题一看题就是把数组分成了k组,k组分别怎么排列后求,然后求k组之和最小,k组里面有n%k组有n/k + 1 个数,有k - n %k 个有n/k个,一个组内部怎样最小当然是按从小到大排最小,内部可以消掉,之等于最大值减最小值,所以所有的数排序,求怎样划分成k组能使和最小。dp方程(i表示有n/k个数):dp[i][j] = min(dp[i-1][j] + a[i * (n/k) + j * (n/k + 1) -1] - a[(i-1) * (n/k) + j * (n/k + 1) -1],dp[i][j-1]+a[i * (n/k) + j * (n/k + 1) -1] - a[i * (n/k) + (j -1)* (n/k + 1) -1],);

Code

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #define MAXN 300001
 5 #define INF 1<<30
 6 using namespace std;
 7
 8 int dp[5001][5001];
 9 int a[MAXN];
10
11 int main()
12 {
13     int n,k;
14     scanf("%d%d",&n,&k);
15     for(int i = 0; i < n; i++)
16         scanf("%d",a+i);
17     sort(a,a+n);
18     int x1 =  k - n % k;
19     int x2 = n % k;
20     k = n/k;
21     dp[0][0] = 0;
22     for(int i = 1; i <= x1; i++)
23         dp[i][0] = dp[i-1][0] + a[i* k - 1] - a[(i-1) * k];
24     for(int j = 1; j <= x2; j++)
25         dp[0][j] = dp[0][j-1] + a[j * (k+1) -1 ] - a[ (j-1) * (k + 1)];
26     for(int i = 1; i <= x1; i++)
27         for(int j = 1; j <= x2; j++)
28         {
29             int k0 = (i-1) * k + j *( k + 1);
30             int k1 = i * k  + (j - 1)* ( k + 1 );
31             dp[i][j] = min((dp[i-1][j] + ((k0 + k) > n ? 0 :(a[k0 + k - 1] - a[k0]))),
32                            (dp[i][j - 1] + ((k1 + k + 1) > n ? 0 : (a[k1 + k] - a[k1]))));
33         }
34     printf("%d\n",dp[x1][x2]);
35     return 0;
36 }
时间: 2024-10-07 06:07:16

51nod1510 最小序列的相关文章

[LeetCode] Minimum Index Sum of Two Lists 两个链表的最小序列和

Suppose Andy and Doris want to choose a restaurant for dinner, and they both have a list of favorite restaurants represented by strings. You need to help them find out their common interest with the least list index sum. If there is a choice tie betw

oracle sql 基础(五):数据定义语言(创建和管理序列、索引、同义词)

许多应用程序要求使用唯一的数字作为主键的值,你即可以在应用程序中构建代码来处理这种需求,也可以用一个序列来产生唯一的数字.如果你想要增进某些查询的性能,你应该考虑创建一个索引,你也可以用索引在列或列的集合上强制唯一性.你可以用同义词为对象提供可替代的名字.下面我们来介绍序列.索引和同义词三个数据库对象.       一.创建和管理序列 序列是用户创建的数据库对象,可以被多个用户共享. 序列的一个典型的用途是创建一个主键的值,它对于每一行必须是唯一的.序列由一个Oracle内部程序产生并增加或减少

[LeetCode] Gas Station,转化为求最大序列的解法,和更简单简单的Jump解法。

LeetCode上 Gas Station是比较经典的一题,它的魅力在于算法足够优秀的情况下,代码可以简化到非常简洁的程度. 原题如下 Gas Station There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. You have a car with an unlimited gas tank and it costs cost[i] of gas to

东软实习之数据库(12)——序列、索引、同义词

#序列 序列的概念 序列是一种用于产生唯一数字列值的数据库对象,一般使用序列自动地生成主码值或唯一键值,序列可以是升序或降序. 序列特点: 可以自动产生唯一数值; 可被多个用户共享: 典型应用是生成主键值,用于标识记录的唯一性: 使用缓存加速序列的访问速度. #创建序列语法 创建序列,必须有CREATE SEQUENCE或CREATE ANY SEQUENCE权限.  序列被创建后,可以通过查询数据字典视图USER_SEQUENCES查看序列信息. 创建序列 sequence 序列产生器的名称

ACM/ICPC 之 Floyd练习六道(ZOJ2027-POJ2253-POJ2472-POJ1125-POJ1603-POJ2607)

以Floyd解法为主的练习题六道 ZOJ2027-Travelling Fee //可免去一条线路中直接连接两城市的最大旅行费用,求最小总旅行费用 //Time:0Ms Memory:604K #include<iostream> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; #define MAX 205 #define MAXS 12 #define

LIS:最长上升子序列

学习动态规划问题(DP问题)中,其中有一个知识点叫最长上升子序列(longest  increasing subsequence),也可以叫最长非降序子序列,简称LIS.简单说一下自己的心得.(大神可无视..) 我们都知道,动态规划的一个特点就是当前解可以由上一个阶段的解推出, 由此,把我们要求的问题简化成一个更小的子问题.子问题具有相同的求解方式,只不过是规模小了而已.最长上升子序列就符合这一特性.我们要求n个数的最长上升子序列,可以求前n-1个数的最长上升子序列,再跟第n个数进行判断.求前n

CF 500 B. New Year Permutation 并查集

User ainta has a permutation p1, p2, ..., pn. As the New Year is coming, he wants to make his permutation as pretty as possible. Permutation a1, a2, ..., an is prettier than permutation b1, b2, ..., bn, if and only if there exists an integer k (1 ≤ k

HDU 1814 Peaceful Commission

Peaceful Commission Time Limit: 5000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 181464-bit integer IO format: %I64d      Java class name: Main The Public Peace Commission should be legislated in Parliament of The Democra

Android模拟屏幕点击input tap替代解决方案

动机解释 本来直接使用 adb shell -> input 即可模拟 键盘事件,触屏事件keyevent ,text,tap 但是手上的这台目标Android机4.0.3系统的input只支持text和keyevent,不支持tap,无法模拟触屏点击事件. usage: input [text|keyevent] input text <string> input keyevent <event_code> 于是开始寻找模拟触屏的替代解决方案. 最新的Android API