Codeforces 571B Minimization (DP)

来源:互联网 发布:谷歌浏览器 for mac 编辑:程序博客网 时间:2024/04/30 07:16

题意

有一个n个数的序列,给出一个k,可以通过对序列重排让nki=1|AiAi+k|最小,求最小值。

思路

题目相当于分成k组,使得{0,k,2k…},{1,k+1,2k+1…}等这些序列分别的序列更小。
显然对于每一个链就是排序之后得到的绝对值的和最小,通过列项相消就能得到对于序列i他的结果就maximini
可以发现有的链的长度是n/k,有的链的长度是n/k+1。
然后对这些链进行dp,dp[i][j]表示已经取到了i个长链j个短链时的最小和,可以由dp[i-1][j]和dp[i][j-1]转移得到。

代码

#include <stdio.h>#include <string.h>#include <iostream>#include <algorithm>#include <vector>#include <queue>#include <stack>#include <set>#include <map>#include <string>#include <math.h>#include <stdlib.h>#include <time.h>using namespace std;#define LL long long#define Lowbit(x) ((x)&(-x))#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1|1#define MP(a, b) make_pair(a, b)const int INF = 0x3f3f3f3f;const int MOD = 1000000007;const int maxn = 100000 + 7;const double eps = 1e-8;const double PI = acos(-1.0);typedef pair<int, int> pii;LL a[3*maxn];LL dp[5050][5050];int main(){    //freopen("in.txt","r",stdin);    //freopen("out.txt","w",stdout);    int n, k;    scanf("%d%d", &n, &k);    for (int i = 1; i <= n; i++)        scanf("%lld", &a[i]);    sort(a + 1, a + 1 + n);    int l = n / k;    int num1 = n % k;    int num2 = k - n % k;    memset(dp, INF, sizeof(dp));    dp[0][0] = 0;    for (int i = 0; i <= num1; i++)        for (int j = 0; j <= num2; j++)        {            int now = i * (l + 1) + j * l;            if (i) dp[i][j] = min(dp[i][j], dp[i-1][j] + a[now] - a[now-l]);            if (j) dp[i][j] = min(dp[i][j], dp[i][j-1] + a[now] - a[now-(l-1)]);        }    printf("%lld\n", dp[num1][num2]);    return 0;}
0 0
原创粉丝点击