【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 & ...
随机推荐
- 关于qt学习的一点小记录(1)
今日为了应付学校作业要求 决定现学qt来制作界面 毕竟c++不像在这方面c#可以那么方便 qt主要依靠信号.槽来实现类似winform中的消息 鉴于要尽快做完,故而没有细看qt 只是大概了解了下界面的 ...
- hdu 5335 Walk Out(bfs+寻找路径)
Problem Description In an n∗m maze, the right-bottom corner or a written on it. An explorer gets los ...
- 表单javascript checkbox全选 反选 全不选
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http ...
- C基础知识小总结(十)
"如有不正确之处,请指出,谢谢" --Mood <指针和函数> 指针函数 函数指针 <最基本的使用函数指针> ...
- 关闭SQL Server 数据库所有使用连接
使用存储过程终止:在查询分析器下创建终止数据库所有接连的存储过程,通过调用该存储过程可以关闭所有使用该数据库的连接操作.--创建终止使用数据库下所有进程的存储过程,参数为数据库名称use maste ...
- asp.net 发送邮件函数两则
using System.Net.Mail; using System.Text; using System.Net; #region 邮件发送 /// <summary> /// 邮件发 ...
- CSS筛选器简单实例1
1.通配符 <!--筛选器---通配符实例--> <!--支持IE7+ --> <style type="text/css"> *.all { ...
- 学习使用Vim(一)
今天下定决心要逐渐脱离IDE的"comfortable zone",学习使用Vim.以前偶尔使用Vim的经历都是很痛苦的,觉得各种不方便和命令复杂难懂.但既然那么多书都推荐使用Vi ...
- 0128——手势Gesture
UIGestureRecognizer: 1.locationinView 获取手势在某个视图里面的坐标位置 2.delegate监听手势的行为 3.state状态 开始:UIGestureRecog ...
- IIS Hang Troubleshoot
Your website maybe stop working and response very lowly. How to find out the reason? Below are the g ...