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 }

原文地址:https://www.cnblogs.com/Leohh/p/8214560.html

时间: 2024-08-03 04:14:31

Codeforces 571B Minimization:dp + 贪心【前后相消】的相关文章

Codeforces 77C 树形dp + 贪心

题目链接:点击打开链接 题意: 给定n个点, 每个点的豆子数量 下面是一棵树 再给出起点 每走到一个点,就会把那个点的豆子吃掉一颗. 问:回到起点最多能吃掉多少颗豆子 思路:树形dp 对于当前节点u,先把子节点v都走一次. 然后再往返于(u,v) 之间,直到u点没有豆子或者v点没有豆子. dp[u] 表示u点的最大值.a[u] 是u点剩下的豆子数. #include <cstdio> #include <vector> #include <algorithm> #inc

Codeforces 571B Minimization

http://codeforces.com/problemset/problem/571/B 给出一个序列,可以任意调整序列的顺序,使得给出的式子的值最小 思路:我们可以把序列分解,变成k条链,n%k条n/k+1长度的,k-n%k条n/k长度的,然后发现,如果要求这个和最小,那么这些链我们都可以变成递增,而且链里面相邻元素是排序后的相邻元素才是最优的.这么样,我们考虑把数组排序,然后dp 考虑这样dp:f[i][j]代表n/k+1长度的有i条,n/k长度有j条,代表能删掉的最大的数,由于i和j确

Codeforces 459E Pashmak and Graph(dp+贪心)

题目链接:Codeforces 459E Pashmak and Graph 题目大意:给定一张有向图,每条边有它的权值,要求选定一条路线,保证所经过的边权值严格递增,输出最长路径. 解题思路:将边按照权值排序,每次将相同权值的边同时加入,维护每个点作为终止点的最大长度即可. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 3

Codeforces 830A. Office Keys (背包dp+贪心) / (二分+贪心)

题目链接: http://codeforces.com/problemset/problem/830/A 题意: n个人,k个钥匙(n<=k),p表示这些人要到达的位置 给出n个人的位置以及钥匙的位置,问花时间最多的那个人用时最少是多少?? 思路: 二分+贪心: 二分最少时间,需要对a,b位置数组排序,我们check函数只需要从左到右一个一个找过去,因为如果选后边的点,可能会使结果更差,假如当前这个人选后面的点,那可能会选中后面的人可以选的唯一的钥匙,不会使解更优. check(40)的时候答案

codeforces219C - Color Stripe DP+贪心

题意:给你n,k,大意就是说给你一个已经涂满颜色长为n的字符串,现有k种颜色可以选择,问你最少要改变多少个箱子的颜色使得相邻箱子之间颜色不同. 解题思路:当k = 2 时单独讨论,不能用贪心,其余情况都可贪心得到. 解题代码: 1 // File Name: 219c.cpp 2 // Author: darkdream 3 // Created Time: 2014年07月26日 星期六 15时45分56秒 4 5 #include<vector> 6 #include<list>

ZOJ 2109 FatMouse&#39; Trade (背包 dp + 贪心)

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1109 FatMouse prepared M pounds of cat food, ready to trade with the cats guarding the warehouse containing his favorite food, JavaBean. The warehouse has N rooms. The i-th room contains J

Codeforces Round #300——C贪心——Tourist&#39;s Notes

Description A tourist hiked along the mountain range. The hike lasted for n days, during each day the tourist noted height above the sea level. On the i-th day height was equal to some integer hi. The tourist pick smooth enough route for his hike, me

UVALive 4731 dp+贪心

这个题首先要利用题目的特性,先贪心,否则无法进行DP 因为求期望的话,越后面的乘的越大,所以为了得到最小值,应该把概率值降序排序,把大的数跟小的系数相乘 然后这种dp的特性就是转移的时候,由 i推到i+1每次添加一个数,就要考虑这个新数应该和谁放在一组,枚举他放在哪一组即可 dp[i][j]代表当前第i个数有j个分组时候的最小值 dp[i][j]=dp[k][j-1]+i(prefix[i]-prefix[k-1]),k代表枚举第几个数开始和当前新添加的数为一组,prefix为前缀和,为了迅速得

HDU 5303(Delicious Apples- 环上折半dp+贪心)

Delicious Apples Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others) Total Submission(s): 1585    Accepted Submission(s): 514 Problem Description There are n apple trees planted along a cyclic road, which is L metres