CF571B. Minimization(DP)

题意:

给定一个序列,重新排列这个序列使得最小。

题解:

/*
 *author: zlc
 *zucc_acm_lab
 *just do it
 */
#include<bits/stdc++.h> 
using namespace std;
typedef long long ll;
const double pi=acos(-1.0);
const double eps=1e-6;
const int mod=1e9+7;
const ll inf=2e18;
const int maxn=1e6+100;
inline ll read () {ll x=0;ll f=1;char ch=getchar();while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;}
//inline int read () {int x=0;int f=1;char ch=getchar();while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}while (ch>='0'&&ch<='9') {x=x*10+ch-'0';ch=getchar();}return x*f;}
ll qpow (ll a,ll b) {ll res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll dp[5005][5005];
ll a[maxn];
ll n,k;
int main () {
    n=read();
    k=read();
    for (int i=1;i<=n;i++) a[i]=read();
    sort(a+1,a+n+1);
    ll t1=n%k;
    ll t2=k-n%k;
    ll x=n/k+1;
    ll y=n/k;
    for (int i=0;i<5005;i++)
        for (int j=0;j<5005;j++)
            dp[i][j]=inf;
    dp[0][0]=0;
    for (int i=0;i<=t1;i++) {
        for (int j=0;j<=t2;j++) {
            ll tt=i*x+j*y;
            if (i) dp[i][j]=min(dp[i][j],dp[i-1][j]+a[tt]-a[tt-x+1]);
            if (j) dp[i][j]=min(dp[i][j],dp[i][j-1]+a[tt]-a[tt-y+1]);
        }
    }
    printf("%lld\n",dp[t1][t2]);
    return 0;
}

 

posted @ 2020-09-10 20:20  zlc0405  阅读(128)  评论(0编辑  收藏  举报