来自《训练指南》优先级队列的例题。

题目链接: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】优先级队列的更多相关文章

  1. UVa 11997 K Smallest Sums 优先队列&amp;&amp;打有序表&amp;&amp;归并

    UVA - 11997 id=18702" target="_blank" style="color:blue; text-decoration:none&qu ...

  2. UVA 11997 K Smallest Sums 优先队列 多路合并

    vjudge 上题目链接:UVA 11997 题意很简单,就是从 k 个数组(每个数组均包含 k 个正整数)中各取出一个整数相加(所以可以得到 kk 个结果),输出前 k 小的和. 这时训练指南上的一 ...

  3. UVa 11997 K Smallest Sums - 优先队列

    题目大意 有k个长度为k的数组,从每个数组中选出1个数,再把这k个数进行求和,问在所有的这些和中,最小的前k个和. 考虑将前i个数组合并,保留前k个和.然后考虑将第(i + 1)个数组和它合并,保留前 ...

  4. 【UVA–11997 K Smallest Sums 】

    ·哦,这题要用优先队列?那大米饼就扔一个手写堆上去吧! ·英文题,述大意:       输入n个长度为n的序列(题中是k,2<=k<=750).一种结果定义为:从每个序列中都要挑选一个数加 ...

  5. 优先队列 UVA 11997 K Smallest Sums

    题目传送门 题意:训练指南P189 分析:完全参考书上的思路,k^k的表弄成有序表: 表1:A1 + B1 <= A1 + B2 <= .... A1 + Bk 表2:A2 + B1 &l ...

  6. uva 11997 K Smallest Sums 优先队列处理多路归并问题

    题意:K个数组每组K个值,每次从一组中选一个,共K^k种,问前K个小的. 思路:优先队列处理多路归并,每个状态含有K个元素.详见刘汝佳算法指南. #include<iostream> #i ...

  7. UVA 11997 K Smallest Sums (多路归并)

    从包含k个整数的k个数组中各选一个求和,在所有的和中选最小的k个值. 思路是多路归并,对于两个长度为k的有序表按一定顺序选两个数字组成和,(B表已经有序)会形成n个有序表 A1+B1<=A1+B ...

  8. 11997 - K Smallest Sums(优先队列)

    11997 - K Smallest Sums You’re given k arrays, each array has k integers. There are kk ways to pick ...

  9. UVA-11997 K Smallest Sums

    UVA - 11997 K Smallest Sums Time Limit: 1000MS   Memory Limit: Unknown   64bit IO Format: %lld & ...

随机推荐

  1. Sum Root to Leaf Numbers 解答

    Question Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent ...

  2. 高精度快速幂(Java版)

    import java.io.*; import java.math.*; import java.util.*; import java.text.*; public class Main { pu ...

  3. mount命令汇总(转载)

    (一)挂接命令(mount) 首先,介绍一下挂接(mount)命令的使用方法,mount命令参数非常多,这里主要讲一下今天我们要用到的. 命令格式: mount [-t vfstype] [-o op ...

  4. python高级编程(第12章:优化学习)1

    # -*- coding: utf-8 -*-# python:2.x__author__ = 'Administrator'#由于5,6,7,8,9,10,11主要是在包,测试之类的学习所以这边就不 ...

  5. QT绘制系统简介

    #3个类:QPainter,QPainterDevice 和 QPaintEngine 三个类 #qpainter用于执行绘制操作 #QPainterDevice是一个二维空间抽象,允许qpainte ...

  6. Promise 异步执行的同步操作

    Promise 是用来执行异步操作的. 但有时一个异步操作需要等其他的异步操作完成,这时候就可以使用then来做. function loadImageAsync(url) { return new ...

  7. c++之 变量

    变量的基本操作 变量就是一个可以变化的量,变量由变量类型.变量名.初始值(可选)组成,例如: int abc = 10; 变量类型:int 变量名:abc 初始值:10 // 该值为可选项,在创建变量 ...

  8. JS nodeType返回类型

    JS nodeType返回类型 前几天朋友正好问道 这个 js的nodeType是个什么概念(做浏览器底层的)正好遇到这篇文章可以向大家解释下 将HTML DOM中几个容易常用的属性做下记录: nod ...

  9. Spring (二) OOP V.S AOP

    介绍 这是两种不同的编程思想就好比初中数学中学习的横纵坐标,一种是横向的一种是纵向,OOP是代表X轴而AOP代表Y轴,如下图: 数学几乎可以解释生活中所有的现象,无论是物体运动还是静止,也可以通过数学 ...

  10. C++空类中的默认函数

    定义一个空的C++类,例如 class Empty { } 一个空的class在C++编译器处理过后就不再为空,编译器会自动地为我们声明一些member function,一般编译过去就相当于 cla ...