Codeforces - Minimization

首先我是被这么一句话骗了的”In particular, it is allowed not to change order of elements at all.”,后来发现其实可以不管它,所以就可以排序后dp了。

 

分析:    按题目的意思,以及式子,可以想到,分成k组数,每组数计算后的和要最小。
            首先,每一组数得出的结果要最小,由于是|ai – ai+k|的结果最小当然是ai和ai+k是数组a中大小相邻的两个数,那么..那么,当然去排序啦。
            然后,对排序后的数组进行分组,分成k组,每组至少n/k个,至多n/k+1个,而且n/k+1要刚好有n%k个。
            接着,根据经验,dp。

 

/* ***********************************************
Author        :DarkTong
Created Time  :2016/5/29 10:42:05
File Name     :Minimization.cpp
************************************************ */

#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int maxn = 5000 + 100;
const int maxm = 300000 + 100;
typedef long long ll;
const long long INF = 100000000000000000LL;
ll dp[maxn][maxn], n, k;
ll a[maxm], sum[maxm], ts;
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    scanf("%lld%lld", &n, &k);
    for(int i=1;i<=n;++i) scanf("%lld", &a[i]);
    ts=0;
    sort(a+1, a+n+1);
    int tn = n/k, tm = n%k;

        for(int i=1;i<tn;++i) ts+=llabs(a[i]-a[i+1]);
        sum[tn]=ts;
        for(int i=tn,j=1;i<=n;++i,++j) 
        {
            ts += llabs(a[i+1]-a[i]);
            ts -= llabs(a[j]-a[j+1]);
            sum[i+1]=ts;
        }

    for(int i=1;i<=k;++i) dp[0][i]=INF;
    for(int i=1;i<=k;++i)
    {
        dp[i][0] = dp[i-1][0]+sum[i*tn];
        for(int j=1;j<=tm;++j)
        {
            dp[i][j] = min(dp[i-1][j]+sum[i*tn+j], dp[i-1][j-1]+sum[i*tn+j-1]+llabs(a[i*tn+j-1]-a[i*tn+j]));
        }
    }
    printf("%lld\n", dp[k][tm]);
    
    
    return 0;
}
posted @ 2016-05-29 14:40  DarkTong  阅读(253)  评论(0编辑  收藏  举报