[CF571B]Minimization(贪心+DP,好)
Posted coding-gaga
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF571B]Minimization(贪心+DP,好)相关的知识,希望对你有一定的参考价值。
题目链接
http://codeforces.com/problemset/problem/571/B
题意
给数组,得到公式最小值。
题解
- 由题分成的子数组只有两种长度,每种长度的数组数量也是固定的。那么就是如何分,怎么计算目标值。
- 易得子数组内部的目标值等于最大值-最小值。
- 贪心在于原始数组排序,分出的一段段认为是直接由排序的原数组切割得到的,无交叉。想一想很有道理。
- 那么就是如何切割。DP即可。DP[i][j]表示i个长度1的子数组和j个长度2个子数组得到的目标值的最小值。DP[cntl1][cntl2]即是所求。
- 事实上,得到切割完的所有连续的子数组,是我们要拆开交错排列的数组。
- 最后要估计一下时间复杂度
代码
import java.util.Arrays;
import java.util.Scanner;
public class Main
public static void main(String args[])
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int k=in.nextInt();
int[] arr=new int[n+1];
for(int i=1;i<=n;++i)
arr[i]=in.nextInt();
Arrays.sort(arr,1,n+1);//
//两种长度的子数组长度和数量
int cntLong=n%k;
int cntShort=k-cntLong;
int lenLong=n/k+1;
int lenShort=n/k;
//dp
int[][] dp=new int[cntLong+1][cntShort+1];//
for(int i=0;i<=cntLong;++i) //
Arrays.fill(dp[i], Integer.MAX_VALUE);//
dp[0][0]=0;
for(int i=0;i<=cntLong;++i) //
for(int j=0;j<=cntShort;++j) //
if(i!=0)
int idxStart=(i-1)*lenLong+j*lenShort+1;
int idxEnd=i*lenLong+j*lenShort;
dp[i][j]=Math.min(dp[i][j], dp[i-1][j]+arr[idxEnd]-arr[idxStart]);
if(j!=0)
int idxStart=i*lenLong+(j-1)*lenShort+1;
int idxEnd=i*lenLong+j*lenShort;
dp[i][j]=Math.min(dp[i][j], dp[i][j-1]+arr[idxEnd]-arr[idxStart]);
System.out.println(dp[cntLong][cntShort]);//
以上是关于[CF571B]Minimization(贪心+DP,好)的主要内容,如果未能解决你的问题,请参考以下文章
CF868F Yet Another Minimization Problem
CF868F Yet Another Minimization Problem 题解