【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 & ...
随机推荐
- 方案:抵御 不明SSL证书导致的 中间人攻击
基于SSL数字证书的中间人攻击已经不是一个新技术了,但是我发现很多人并不清楚这种威胁,甚至感觉无所谓,我相信他们是由于短暂的无知蒙蔽了双眼,希望这篇文章可以让更多的人知道这种攻击方式,并清除这种网络威 ...
- UESTC_Dividing Numbers CDOJ 1156
Dividing Numbers Time Limit: 9000/3000MS (Java/Others) Memory Limit: 262144/262144KB (Java/Other ...
- Inorder Successor in BST 解答
Question Given a binary search tree and a node in it, find the in-order successor of that node in th ...
- Hdu5737-Differencia(有序表线段树)
题意很直观,我就不说了. 解析:这是我以前没有接触过的线段树类型,有序表线段树,每个节点申请了两段空间,主要是为了保存左边儿子会有多少比v小的,右边儿子会有多少比v小 的,所以在建树过程中要归并排序. ...
- 《Java程序员面试笔试宝典》之组合与继承有什么区别
组合和继承是面向对象中两种代码复用的方式.组合是指在新类里面创建原有类的对象,重复利用已有类的功能.继承是面向对象的主要特性之一,它允许设计人员根据其它类的实现来定义一个类的实现.组合和继承都允许在新 ...
- SqlServer经典函数之数字去零
需求: 针对带有小数点的数字信息,去除小数点后多余的零 可能存在的情况: 1.精度范围内,出现多余的零 eg:1234.3400 想要的结果为1234.34 2.精度变大出现的多余的零, ...
- phpcms 缓存
PHPCMS设置和读取缓存文件 PHPCMS开发中经常用到读取文件缓存,比如常见的当前站点类别,是保存在缓存文件中的,读取的时候 用:$this->categorys = getcache(‘c ...
- linux下修改防火墙端口对外开放方法
---linix CentOS7的防火墙换成了firewall了,这里做一些记录,下面是一些命令:添加例外端口:# firewall-cmd --add-port=8080/tcp删除例外端口:# f ...
- android jni ——Field & Method --> Accessing Field
现在我们知道了怎样使用native code访问简单的数据类型和引用参考类型(string,array),下面我们来介绍怎样让jni代码去访问java中的成员变量和成员函数,然后可以再jni中回调ja ...
- java与.net比较学习系列(6) 数组
这一篇文章要总结的内容是数组,数组可以简单地看成是同种数据类型变量的集合,它在我们的开发中经常用到,我们主要从以下几个方面进行总结: 1,数组的创建和初始化 2,数组的访问和遍历 3,数组的总结 数组 ...