• hdu4261(优先队列+DP)


    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4261

    问题描述
    “这里数字太多了!”您的老板吼叫。“我应该如何理解所有这些?把它放下来!估计!” 
    您很失望。生成这些数字需要大量的工作。但是,您将按照老板的要求去做。
    您决定通过以下方式进行估算:您拥有一个数字数组A。您将其划分为k个连续的部分,它们的大小不一定相同。然后,您将使用一个数字来估计整个部分。换句话说,对于大小为n的数组A,您想要创建另一个大小为n的数组B,它具有k个连续的部分。如果i和j在同一部分,则B [i] = B [j]。您想使误差最小化,表示为差的绝对值之和(Σ | A [i] -B [i] |)。
    输入项
    输入中将有几个测试用例。每个测试用例将与两个整数开始在一条线上,Ñ(1≤ Ñ ≤2,000)和ķ(1≤ ķ ≤25,ķ ≤ Ñ),其中Ñ是阵列的尺寸,并且ķ是连续数用于估算的部分。数组A将在接下来的n行中,每行一个整数。A的每个整数元素的范围为-10,000至10,000(含)。输入将以两个0结束。
    输出量
    对于每个测试用例,在其自己的行上输出一个整数,这是您可以实现的最小误差。不要输出多余的空格,也不要用空行分隔答案。所有可能的输入都会产生答案,该答案将适合有符号的64位整数
    样本输入
    7 2
    6
    5
    4
    3
    2
    1
    7
    0 0
    Sample Output
    9

    题意:给出一个序列A,分为K个部分,然后每个部分给出一个B,使得所有的sigma(|Ai-Bi|)最小

    解题思路:首先定义状态dp【i】【j】:前i个分成j块的最小代价。那么很容易得到dp【i】【j】=min(dp【m】【i-1】+(m+1到i分成一块的代价))。那么问题的关键就成了求出所有可能的区间分成一块的代价了。对于每个区间,很容易想到:把B数组的这个块赋值为相应A数组的块的中位数了,此时代价最小。至于怎么求中位数,可以定义两个优先队列,一个值大的优先,一个值小的优先,那每个区间平均放到这两个队列,那么中位数就为这两个区间队首的某一个了,接着求这个区间的代价就可以了。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=2e3+5;
    int dp[maxn][30];
    int tem[maxn][maxn];
    int a[maxn];
    const int inf=0x3f3f3f3f;
    priority_queue<int,vector<int>,greater<int> >que1;
    priority_queue<int> que2;
    int main(){
    	int n,k;
    	while(scanf("%d%d",&n,&k)!=EOF){
    		if(n==0&&k==0){
    			return 0;
    		}
    		for(int i=0;i<=n;i++){
    			for(int j=1;j<=k;j++){
    				dp[i][j]=inf;
    			}
    			dp[i][i]=0;
    		}
    		for(int i=1;i<=n;i++){
    			scanf("%d",&a[i]);
    			
    		}
    		for(int i=1;i<=n;i++){
    			while(!que1.empty())que1.pop();
    			while(!que2.empty())que2.pop();
    			int sum1,sum2;
    			sum1=sum2=0;
    			for(int j=i;j>=1;j--){
    				int l1=(i-j+2)/2;
    				int l2=(i-j+1)/2;
    				int t=a[j];
    				if(que1.empty()){
    					sum1+=t;
    					que1.push(t);
    				}
    				else{
    					if(t>que1.top()){
    						sum1+=t-que1.top();
    						que1.push(t);
    						t=que1.top();
    						que1.pop();
    					}
    					if(!que2.empty()&&t<que2.top()){
    						sum2+=t-que2.top();
    						que2.push(t);
    						t=que2.top();
    						que2.pop();
    					}
    					if(que1.size()<l1){
    						sum1+=t;
    						que1.push(t);
    					}
    					else{
    						sum2+=t;
    						que2.push(t);
    					}
    				}
    				t=que1.top();
    				int t1=-1;
    				if(!que2.empty())
    				 	t1=que2.top();
    				if((i-j+1)&1){
    					tem[j][i]=sum1-t*l1+t*l2-sum2;
    				}
    				else{
    					tem[j][i]=min(sum1-t*l1+t*l2-sum2,sum1-t1*l1+t1*l2-sum2);
    				}
    			}
    		}
    		for(int i=1;i<=n;i++){
    			dp[i][1]=tem[1][i];
    		}
    		for(int i=2;i<=k;i++){
    			for(int j=i;j<=n;j++){
    				for(int m=1;m<j;m++){
    					dp[j][i]=min(dp[j][i],dp[m][i-1]+tem[m+1][j]);
    				}
    			}	
    		}
    		printf("%d
    ",dp[n][k]);
    	}
    	return 0;
    } 
    

      

     
  • 相关阅读:
    进阶之路 | 奇妙的Drawable之旅
    进阶之路 | 奇妙的Animation之旅
    进阶之路 | 奇妙的四大组件之旅
    Laravel
    Laravel 入门
    面试:给我说说你平时是如何优化MySQL的?
    EXPLAIN 查看 SQL 执行计划
    常见的图文布局
    常见的图文布局
    CSS3 的 filter(滤镜) 属性
  • 原文地址:https://www.cnblogs.com/Zhi-71/p/11862522.html
Copyright © 2020-2023  润新知