【UVA 11997 K Smallest Sums】优先级队列
来自《训练指南》优先级队列的例题。
题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18702
题意:给定k个整数数组,各包含k个元素。在每个数组中取一个元素加起来,可以得到kk个和,求这些和中最小的k个值(不去重)。
数据范围:k [2, 750]
思路:暴力枚举k^k不可取。
“先来看问题的简化版:给出两个长度为k的数组A和B,分别在A和B中任取一个数并相加,可以得到k^2个和,求这些和中最小的k个。”
首先把A, B从小到大排序。由于只求最小的前k个值,我们可以先假定B[0]与A的k个元素分别相加得到的元素集合S就是最小的k个和,然后每次取出S的最小值Smin保存到结果数组R中,并把Smin减去B[i]、加上B[i+1]后得到的值再放回集合S中,保持S的大小总为k。这样经过k轮取出-放回操作后,R中的k个元素就是结果。我们把这一操作过程叫作A,B的合并。合并一次的复杂度为O(klogk)
S需要k次插入和删除,每次只取最小值,因此数据结构选用完全二叉堆实现的优先级队列很合适。
现在由两个数组A,B扩展到k个数组A1~Ak,只需把A1看作A, 依次处理 i: 2~k,每次把Ai合并到A1中,这样经过k次两两合并后,A1中的k个数就是结果。总的复杂度O(k2logk)
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int MAX_K = ; struct Elem{
int sum, b;
Elem(int s, int b):sum(s), b(b){}
Elem& operator = (const Elem& e){
sum = e.sum;
b = e.b;
return *this;
}
bool operator < (const Elem& e) const{
return sum > e.sum; //小顶堆
}
}; void merge(int* A, int* B, int n){
priority_queue<Elem> pq;
for(int i=; i<n; i++){
pq.push(Elem(A[i] + B[], ));
}
for(int i=; i<n; i++){
Elem e = pq.top();
A[i] = e.sum;
pq.pop();
e.sum = e.sum - B[e.b] + B[e.b+];
e.b = e.b + ;
pq.push(e);
}
// for(int i=0; i<n; i++){
// printf("%d ", A[i]);
// }
// printf("\n");
} int k;
int a[MAX_K], b[MAX_K]; int main()
{
freopen("11997.txt", "r", stdin);
while(~scanf("%d", &k)){
for(int i=; i<k; i++){
scanf("%d", &a[i]);
}
sort(a, a+k);
for(int i=; i<k; i++){
for(int j=; j<k; j++){
scanf("%d", &b[j]);
}
sort(b, b+k);
merge(a, b, k);
}
printf("%d", a[]);
for(int i=; i<k; i++){
printf(" %d", a[i]);
}
printf("\n");
}
return ;
}
【UVA 11997 K Smallest Sums】优先级队列的更多相关文章
- UVa 11997 K Smallest Sums 优先队列&&打有序表&&归并
UVA - 11997 id=18702" target="_blank" style="color:blue; text-decoration:none&qu ...
- UVA 11997 K Smallest Sums 优先队列 多路合并
vjudge 上题目链接:UVA 11997 题意很简单,就是从 k 个数组(每个数组均包含 k 个正整数)中各取出一个整数相加(所以可以得到 kk 个结果),输出前 k 小的和. 这时训练指南上的一 ...
- UVa 11997 K Smallest Sums - 优先队列
题目大意 有k个长度为k的数组,从每个数组中选出1个数,再把这k个数进行求和,问在所有的这些和中,最小的前k个和. 考虑将前i个数组合并,保留前k个和.然后考虑将第(i + 1)个数组和它合并,保留前 ...
- 【UVA–11997 K Smallest Sums 】
·哦,这题要用优先队列?那大米饼就扔一个手写堆上去吧! ·英文题,述大意: 输入n个长度为n的序列(题中是k,2<=k<=750).一种结果定义为:从每个序列中都要挑选一个数加 ...
- 优先队列 UVA 11997 K Smallest Sums
题目传送门 题意:训练指南P189 分析:完全参考书上的思路,k^k的表弄成有序表: 表1:A1 + B1 <= A1 + B2 <= .... A1 + Bk 表2:A2 + B1 &l ...
- uva 11997 K Smallest Sums 优先队列处理多路归并问题
题意:K个数组每组K个值,每次从一组中选一个,共K^k种,问前K个小的. 思路:优先队列处理多路归并,每个状态含有K个元素.详见刘汝佳算法指南. #include<iostream> #i ...
- UVA 11997 K Smallest Sums (多路归并)
从包含k个整数的k个数组中各选一个求和,在所有的和中选最小的k个值. 思路是多路归并,对于两个长度为k的有序表按一定顺序选两个数字组成和,(B表已经有序)会形成n个有序表 A1+B1<=A1+B ...
- 11997 - K Smallest Sums(优先队列)
11997 - K Smallest Sums You’re given k arrays, each array has k integers. There are kk ways to pick ...
- UVA-11997 K Smallest Sums
UVA - 11997 K Smallest Sums Time Limit: 1000MS Memory Limit: Unknown 64bit IO Format: %lld & ...
随机推荐
- uva10245-The Closest Pair Problem(平面上的点分治)
解析:平面上的点分治,先递归得到左右子区间的最小值d,再处理改区间,肯定不会考虑哪些距离已经大于d的点对,对y坐标归并排序,然后从小到大开始枚举更新d,对于某个点,x轴方向只用考虑[x-d,x+d]( ...
- Java宝典(四)------Java中也存在内存泄露。
--Java中会存在内存泄露吗? --如果你想当然的以为Java里有了垃圾回收机制就不会存在内存泄露,那你就错了. Java里也会存在内存泄露! 我们慢慢来分析. 所谓内存泄露就是指一个不再被程序使用 ...
- UIScrollView上面放一个UIScrollView或者UITableView拖动时候 View出现一闪一闪解决办法
在项目中发现一个问题: 创建一个UIScrollView 上面放一个scrollView或者TableView,拖动scrollview或TableView 画面出现一闪一闪的情况. 解决办法设置一下 ...
- jdbc和数据库的应用
jdbc是Java Data Base Connectivity(java数据库连接): 是一种用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问,它由一组用Java语言编写的类和 ...
- Exchange Server 2010升级到Exchange Server 2013概览
- [转]laravel 4之视图及Responses
http://dingjiannan.com/2013/laravel-responses/ laravel 4之视图及Responses 16 Aug 2013 Laravel的Response ...
- Afianl加载网络图片(延续)
上一页"已经谈到了如何使用Afianl网络负载的图片和下载文件,本文将继续介绍使用Afinal使用网络负载图片,主绑定listview采用: 看效果图: listview在滑动过程中没用明显 ...
- SSO之CAS基础及应用视频教程(2)
CAS介绍 CAS = Central Authentication Service,中央认证服务.CAS 是 Yale 大学发起的一个开源项目,能够为 Web 应用系统或者非Web应用系统提供一种可 ...
- textarea 的最大高度以及最小高度
<script type="text/javascript"> $(function(){ $("#textarea3").textareaAuto ...
- 修改sqlserver2008中表的schema
schema类似命名空间,相同schema中不能有同样的表名,不用schema下可以有相同的表名 修改schema的方法: 在数据库的 安全性->架构 中添加一个新的架构 找到要修改的表,右击设 ...