zoukankan      html  css  js  c++  java
  • 【51Nod】1510 最小化序列 贪心+动态规划

    【题目】1510 最小化序列
    【题意】给定长度为n的数组A和数字k,要求重排列数组从而最小化:

    $$ans=sum_{i=1}^{n-k}|A_i-A_{i+k}|$$

    输出最小的ans,(n leq 3*10^5,k leq 5000,-10^9 leq A_i leq 10^9)
    【算法】贪心+动态规划
    先对序列从小到大排序,通过贪心容易发现连续的段在一起时最优。所以实际上要求将序列分成(k)段,其中(n%k)个大段和其它小段,小段的段长是(g=frac{n}{k}),大段段长+1。
    (f_{i,j})表示前面i个段有j个大段的最小代价,那么:

    $$f_{i,j}=min { f_{i-1,j-1}+a_{ig+j}-a_{(i-1)g+j},f_{i-1,j}+a_{ig+j}-a_{(i-1)g+j+1} } $$

    复杂度(O(k^2+n log n))
    注意:开long long会爆空间除非用滚动数组。不用ll的话必须用unsigned int否则中间过程会爆int。初始化f[0][0]=1,f[0][1~k]=inf非常重要。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    bool isdigit(char c){return c>='0'&&c<='9';}
    int read(){
    	int s=0,t=1;char c;
    	while(!isdigit(c=getchar()))if(c=='-')t=-1;
    	do{s=s*10+c-'0';}while(isdigit(c=getchar()));
    	return s*t;
    }
    using namespace std;
    #define ll long long
    const int maxn=300010,kind=5010;
    int n,k,a[maxn],ans;
    unsigned int f[2][kind];
    int main(){
    	n=read();k=read();
    	for(int i=1;i<=n;i++)a[i]=read();
    	sort(a+1,a+n+1);
    	int g=n/k,num=n%k;
    	int x=0;
    	f[x][0]=0;for(int i=1;i<=k;i++)f[x][i]=2000000001;
    	for(int i=1;i<=k;i++){
    		x=1-x;
    		f[x][0]=f[1-x][0]+a[i*g]-a[(i-1)*g+1];//long long
    		for(int j=1;j<=k;j++)f[x][j]=min(f[1-x][j-1]+a[i*g+j]-a[(i-1)*g+j],f[1-x][j]+a[i*g+j]-a[(i-1)*g+j+1]);
    	}
    	printf("%d",f[x][num]);	
    	return 0;
    }
  • 相关阅读:
    框架学习之Spring 前言
    XML学习第二节 DTD介绍
    JavaScript重学 V512视频
    框架学习之Spring 第五节 SSH整合开发[Spring2.5+Hibernate3.3+Struts2]
    XML学习第一节 XML简介
    框架学习之Spring 第四节 Spring集成JDBC组件开发
    歌曲:酒干倘卖无 背后的故事
    又要被学校开除了!
    linux常用命令
    心情
  • 原文地址:https://www.cnblogs.com/onioncyc/p/9080927.html
Copyright © 2011-2022 走看看