首先我是被这么一句话骗了的”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; }
时间: 2024-10-09 11:07:35