HDU 4261 Estimation (DP+优先队列优化)
来源:互联网 发布:单片机开发步骤 编辑:程序博客网 时间:2024/05/22 14:26
转载请注明出处,谢谢http://blog.csdn.net/acm_cxlove/article/details/7854526 by---cxlove
题目:给出一个序列A,分为K个部分,然后每个部分给出一个B,使得所有的sigma(|Ai-Bi|)最小
http://acm.hdu.edu.cn/showproblem.php?pid=4261
对于某一段,肯定是将B取为他们的中位数是最优的,开始以为是平均数,弱爆了。
容易想到DP可做,dp[i][j]表示前i个数,分为j个部分的最优解。
dp[i][j]=min(dp[r][j-1]+sum(r+1,j)) 其中sum(r+1,j)表示 从r+1到j分为一个部分的最小差值
DP是n^2*k,但是sum部分的复杂度还比较高。必须先预处理
用双堆优化,写成双优先队列优化。
维护两个堆,一个存比较小的数,一个存比较大的数,新加的数容易判断和当前的中位数的大小,加入其中的堆
然后维护一下两个堆的数量均衡,保证中位数的位置确定,我取的是大堆中的最小值。
结果就是大堆和与小堆和的差,注意奇数个的情况。
另外这题卡时比较紧,注意姿势
#include<iostream>#include<cstdio>#include<cstring>#include<queue>#define inf 1<<29using namespace std;int n,k,a[2005];int b[2005][2005]; //存放i到j的最小差值int dp[2005][26]={0}; //dp[i][j]表示前i个数,分为j段的最优解//以下两个优先队列,记录中位数//如果为奇数个元素,中位数便是大的里面的最小值//如果为偶数则为小的最大值与大的最小值之间的任意数priority_queue<int>lower;priority_queue<int,vector<int>,greater<int> >upper;int main(){ while(scanf("%d%d",&n,&k)!=EOF&&n+k){ for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) for(int j=0;j<=k;j++) dp[i][j]=inf; for(int i=1;i<=n;i++){ while(!lower.empty()) lower.pop(); while(!upper.empty()) upper.pop(); int sum=0; //sum表示大堆和与小堆和的差 for(int j=i;j<=n;j++){ //判断是加入小的,还是大的 if(lower.empty()||a[j]<=lower.top()){ lower.push(a[j]); sum-=a[j]; } else{ upper.push(a[j]); sum+=a[j]; } //计算小堆里面的数量,大堆里面的数量 int low=(j-i+1)/2,high=(j-i+1)-low; //作一次调整,使得数量保持一致 if(lower.size()>low){ upper.push(lower.top()); sum+=lower.top()*2; lower.pop(); } if(upper.size()>high){ lower.push(upper.top()); sum-=upper.top()*2; upper.pop(); } //前面的调整可能使顺序错乱,将小的里面的最大值和大的里面的最大值比较 //作交换调整 while(lower.size()&&upper.size()&&lower.top()>upper.top()){ int u=lower.top(),v=upper.top(); lower.pop();upper.pop(); sum=sum+2*u-2*v; lower.push(v);upper.push(u); } int ans=sum; //如果个数为奇数,说明中位数为大的里面的最小值,要减掉 if(high>low) ans-=upper.top(); b[i][j]=ans; } } //n^2*k的DP for(int i=1;i<=n;i++){ for(int j=1;j<=k;j++){ for(int r=0;r<i;r++) dp[i][j]=(dp[r][j-1]+b[r+1][i])<dp[i][j]?(dp[r][j-1]+b[r+1][i]):dp[i][j]; } } printf("%d\n",dp[n][k]); } return 0;}
- HDU 4261 Estimation (DP+优先队列优化)
- 【HDU4261】Estimation-DP+优先队列优化
- hdu 4261 Estimation (优先队列预处理+DP)
- la4327 优先队列优化dp
- hdu 1142 dijstra+优先队列优化+树状dp优化(简单dfs)
- hdu 4362 Dragon Ball(优先队列+dp)
- hdu 2680 dijkstra 使用优先队列优化
- hdu 2824 Dogs(BFS, 优先队列优化)
- HDU 2544 dijk优化探索---优先队列优化
- hdu 2112 HDU Today 优先队列优化的Dijkstra+map
- Robotruck----UVA1169----DP(优先队列的优化)
- HDU 4374 单调队列优化 DP
- hdu 4374 dp+单调队列优化
- hdu 4374 单调队列优化DP
- hdu 3401 Trade(DP+单调队列优化)
- hdu 3530 Subsequence(DP+单调队列优化)
- hdu 3401 Trade 单调队列优化dp
- hdu 3401 单调队列优化+dp
- PHP的三种安装模式的比较
- 数据库主动式通知编程
- Java使用MulticastSocket实现多点广播
- 通过Eclipse的插件自动下载和更新功能
- Linux安装Tomcat6.0
- HDU 4261 Estimation (DP+优先队列优化)
- 指针数组和数组指针
- paip.提升安全性--------用户密码控件方案总结
- imageICK
- 关于php学习笔记五
- android 从应用程序连接到市场代码
- 深度探讨 PHP 之性能
- 网络访问技术
- 安装subversion