不错的题。
容易想到按模
K
分类 。每类的贡献时独立的,就是
如何分配数分在哪一类呢 ? 发现我们一定是把连续的数放在一起比较优。
这样贪心的分析一下就变的很简单了,直接把
a
数组排序。然后就是要把a分成
注意到段的长度只有两种。所以
DP
就好啦。
fi,j
表示第一种长度的已经有
i
个,第二种已经有
复杂度
O(K2)
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=300005,maxk=5005;
typedef long long LL;
int n,K,a[maxn],cnt1,cnt2,len1,len2;
LL f[maxk][maxk];
int main(){
freopen("cf571B.in","r",stdin);
freopen("cf571B.out","w",stdout);
scanf("%d%d",&n,&K);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
sort(a+1,a+1+n);
len1=(n-K)/K+1; len2=len1+1;
for(int i=1;i<=K;i++) if((n-i)/K+1==len1) cnt1++; else cnt2++;
memset(f,63,sizeof(f)); f[0][0]=0;
for(int i=0;i<=cnt1;i++)
for(int j=0;j<=cnt2;j++){
int now=i*len1+j*len2;
if(i<cnt1) f[i+1][j]=min(f[i+1][j],f[i][j]+a[now+len1]-a[now+1]);
if(j<cnt2) f[i][j+1]=min(f[i][j+1],f[i][j]+a[now+len2]-a[now+1]);
}
printf("%I64d\n",f[cnt1][cnt2]);
return 0;
}