Codeforces 571B Minimization:dp + 贪心前后相消

Posted Leohh

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces 571B Minimization:dp + 贪心前后相消相关的知识,希望对你有一定的参考价值。

题目链接:http://codeforces.com/problemset/problem/571/B

题意:

  给你一个长度为n的数列a[i]。

  现在你可以随意改变数字的位置,问你 ∑| a[i] - a[i+k] | 的最小值(1 <= i <= n-k)。

 

题解:

  将a[i]拆成若干个子序列s[j],子序列中相邻两数在a[i]中的距离为k。

  此时原式 = ∑(子序列s[j]内部之差的和)

 

  显然,要想使子序列s[j]内部之差的和尽可能小,子序列s[j]内部一定为升序。

  显然,要想使 ∑(子序列s[j]内部之差的和)尽可能小,所有子序列s[j]一定是由a[i]升序排序后分割而来。

 

  可以发现,拆出的子序列中:

    有 n2 = n%k 个子序列长度为 l1 = n/k+1

    有 n1 = k-n%k 个子序列长度为 l2 = n/k

 

  此时:

    原式 = ∑ (s[2]-s[1]+s[3]-s[2]+s[4]-s[3]...)

  前后相消之后就是:

 

    原式 = ∑ (s[i][end] - s[i][1])

  此时题目就变成了:

    先将a[i]排序,然后将a[i]分割成n1个长为l1的子串,以及n2个长为l2的子串。

    让你使得 ∑ (s[i][end] - s[i][1])最小。

 

  表示状态:

    dp[i][j]

    表示从头开始分割,已经分割出了i个长为l1的子串,以及j个长为l2的子串。

 

  找出答案:

    ans = dp[n1][n2]

 

  如何转移:

    if(i) dp[i][j] = min(dp[i][j], dp[i-1][j]+a[start1]-a[end1])

    if(j) dp[i][j] = min(dp[i][j], dp[i][j-1]+a[start2]-a[end2])

    start1/2, end1/2分别是新分割出的子串的首位与末尾。

 

  边界条件:

    dp[0][0] = 0

    others = INF

 

AC Code:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <algorithm>
 5 #define MAX_N 300005
 6 #define MAX_S 5005
 7 
 8 using namespace std;
 9 
10 int n,k;
11 int a[MAX_N];
12 long long dp[MAX_S][MAX_S];
13 
14 int main()
15 {
16     cin>>n>>k;
17     for(int i=1;i<=n;i++) cin>>a[i];
18     sort(a+1,a+n+1);
19     int n1=n%k,n2=k-n%k;
20     int l1=n/k+1,l2=n/k;
21     memset(dp,0x3f,sizeof(dp));
22     dp[0][0]=0;
23     for(int i=0;i<=n1;i++)
24     {
25         for(int j=0;j<=n2;j++)
26         {
27             if(i) dp[i][j]=min(dp[i][j],dp[i-1][j]+a[i*l1+j*l2]-a[(i-1)*l1+j*l2+1]);
28             if(j) dp[i][j]=min(dp[i][j],dp[i][j-1]+a[i*l1+j*l2]-a[i*l1+(j-1)*l2+1]);
29         }
30     }
31     cout<<dp[n1][n2]<<endl;
32 }

 

以上是关于Codeforces 571B Minimization:dp + 贪心前后相消的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces 571B Minimization:dp + 贪心前后相消

[CF571B]Minimization(贪心+DP,好)

codeforces上怎么看测试数据

如何看codeforces做了多少题

codeforces上怎么看测试数据

codeforces比赛后怎么看题解和答案