codeforces 317 B. Minimization

来源:互联网 发布:cad迷你看图mac破解版 编辑:程序博客网 时间:2024/04/25 19:13

题目描述:

You’ve got array A, consisting of n integers and a positive integer k. Array A is indexed by integers from 1 to n.

You need to permute the array elements so that value
(就是错k个相减)

became minimal possible. In particular, it is allowed not to change order of elements at all.

Input

The first line contains two integers n, k (2 ≤ n ≤ 3·105, 1 ≤ k ≤ min(5000, n - 1)).

The second line contains n integers A[1], A[2], …, A[n] ( - 109 ≤ A[i] ≤ 109), separate by spaces — elements of the array A.

Output

Print the minimum possible value of the sum described in the statement.

题解:

很好的一道题.性质要一直往前想.
首先,我们很容易发现分组成k组之后k组之间就没关系了
其次,k组内部怎么好呢?如果都是一样的就好了,一样的不够了,就用最接近的。关键来了,一组内一定要是整体升序(当然降序也。。不妨),这个性质来的很关键,并且我们是想要挨着越近越好。所以就是连续的一段升序。那么一共有k组,我们给谁呢?
最后,现在我们知道了先把a升序排个序,然后一段一段的挑出来,要连续挑出k段,一个长n/k,一个长n/k+1,我们之后dp【i】【j】,表示有i个第一类型,j个第二类型。o(1)转移。

重点:

(1)性质的感觉+猜测。 想要什么就假设什么然后观察相近的。 记住排序,连续则写贪心点。
(2)dp的工具使用

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <string>#include <cmath>#include <ctype.h>#include <limits.h>#include <cstdlib>#include <algorithm>#include <vector>#include <queue>#include <map>#include <stack>#include <set>#include <bitset>#define CLR(a) memset(a, 0, sizeof(a))#define REP(i, a, b) for(int i = a;i < b;i++)#define REP_D(i, a, b) for(int i = a;i <= b;i++)typedef long long ll;using namespace std;const int maxn = 3e5+100;const int maxK = 5000+10;const ll INF = 1e18;int a[maxn], n, k;ll f[maxK][maxK];ll gao(int i, int j, int len){    int s = i*(n/k)+j*(n/k+1)+1;    int t = s+len-1;    return a[t]-a[s];}void solve(){    sort(a+1, a+1+n);    int ni = k - n%k;//n/k    int nj = n%k;//n/k+1    f[0][0] = 0;    for(int i = 0;i<=ni;i++)    {        for(int j = 0;j<=nj;j++)        {            if(i==0&&j==0)                continue;            f[i][j] = INF;            if(i>=1)            {                f[i][j] = min(f[i][j], f[i-1][j]+gao(i-1, j, n/k));            }            if(j>=1)            {                f[i][j] = min(f[i][j], f[i][j-1]+gao(i, j-1, n/k+1));            }        }    }    printf("%I64d\n", f[ni][nj]);}int main(){    freopen("2Bin.txt", "r", stdin);    //freopen("3Bout.txt", "w", stdout);    while(scanf("%d%d", &n, &k)!=EOF)    {        for(int i = 1;i<=n;i++)            scanf("%d", &a[i]);        solve();    }    return 0;}
0 0
原创粉丝点击