zoukankan      html  css  js  c++  java
  • [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]);//
    	}	
    }
    
  • 相关阅读:
    如何测得存储空间大小
    打印阿斯科码 和 打印字符
    正常血压
    c语言知识(1)
    子组件和父组件
    RESTful风格API
    django APIview使用
    django 基础
    npm install异常error code EPERM
    springsecurity 多httpsecurity配置
  • 原文地址:https://www.cnblogs.com/coding-gaga/p/11001392.html
Copyright © 2011-2022 走看看