【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)

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <queue>
 4 using namespace std;
 5 const int MAX_K = 760;
 6
 7 struct Elem{
 8     int sum, b;
 9     Elem(int s, int b):sum(s), b(b){}
10     Elem& operator = (const Elem& e){
11         sum = e.sum;
12         b = e.b;
13         return *this;
14     }
15     bool operator < (const Elem& e) const{
16         return sum > e.sum; //小顶堆
17     }
18 };
19
20 void merge(int* A, int* B, int n){
21     priority_queue<Elem> pq;
22     for(int i=0; i<n; i++){
23         pq.push(Elem(A[i] + B[0], 0));
24     }
25     for(int i=0; i<n; i++){
26         Elem e = pq.top();
27         A[i] = e.sum;
28         pq.pop();
29         e.sum = e.sum - B[e.b] + B[e.b+1];
30         e.b = e.b + 1;
31         pq.push(e);
32     }
33 //    for(int i=0; i<n; i++){
34 //        printf("%d ", A[i]);
35 //    }
36 //    printf("\n");
37 }
38
39 int k;
40 int a[MAX_K], b[MAX_K];
41
42 int main()
43 {
44     freopen("11997.txt", "r", stdin);
45     while(~scanf("%d", &k)){
46         for(int i=0; i<k; i++){
47             scanf("%d", &a[i]);
48         }
49         sort(a, a+k);
50         for(int i=1; i<k; i++){
51             for(int j=0; j<k; j++){
52                 scanf("%d", &b[j]);
53             }
54             sort(b, b+k);
55             merge(a, b, k);
56         }
57         printf("%d", a[0]);
58         for(int i=1; i<k; i++){
59             printf(" %d", a[i]);
60         }
61         printf("\n");
62     }
63     return 0;
64 }
时间: 2024-11-01 00:16:42

【UVA 11997 K Smallest Sums】优先级队列的相关文章

浅谈算法和数据结构 五 优先级队列与堆排序

在很多应用中,我们通常需要按照优先级情况对待处理对象进行处理,比如首先处理优先级最高的对象,然后处理次高的对象.最简单的一个例子就是,在手机上玩游戏的时候,如果有来电,那么系统应该优先处理打进来的电话. 在这种情况下,我们的数据结构应该提供两个最基本的操作,一个是返回最高优先级对象,一个是添加新的对象.这种数据结构就是优先级队列(Priority Queue) . 本文首先介绍优先级队列的定义,有序和无序数组以及堆数据结构实现优先级队列,最后介绍了基于优先级队列的堆排序(Heap Sort) 更

解析Java中PriorityQueue优先级队列结构的源码及用法_java

一.PriorityQueue的数据结构 JDK7中PriorityQueue(优先级队列)的数据结构是二叉堆.准确的说是一个最小堆. 二叉堆是一个特殊的堆, 它近似完全二叉树.二叉堆满足特性:父节点的键值总是保持固定的序关系于任何一个子节点的键值,且每个节点的左子树和右子树都是一个二叉堆. 当父节点的键值总是大于或等于任何一个子节点的键值时为最大堆. 当父节点的键值总是小于或等于任何一个子节点的键值时为最小堆. 下图是一个最大堆 priorityQueue队头就是给定顺序的最小元素. prio

用C++实现模板优先级队列及堆排序实例

模板优先级队列,数组实现,再熟悉一下常用算法,同时简单的堆排序应用 写了一个是队列自增长,另一个为了演示我还添加了一个叫做FillPq的方法,这个方法可以使用一个数组直接填充到优先级队列里,此时,优先级队列并不优先,然后进行下滤调整,之后建堆完成,输出即可 #include "stdafx.h" template< class T> class PriorityQueue { private: T *pq; int N; int capacity; public: Prio

C++:库函数优先级队列(priority_queue)输出最小值 代码

库函数优先级队列(priority_queue)的实现方式是堆(heap), 默认是输出最大值. 输出最小值, 需要指定参数, priority_queue<int, vector<int>, greater<int> > 代码: /* * main.cpp * * Created on: 2014.7.20 *更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/Programming/cplus/ * Author:

Java数组模拟优先级队列数据结构的实例_java

优先级队列如果我们给每个元素都分配一个数字来标记其优先级,不妨设较小的数字具有较高的优先级,这样我们就可以在一个集合中访问优先级最高的元素并对其进行查找和删除操作了.这样,我们就引入了优先级队列 这种数据结构. 优先级队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有(1)查找(2)插入一个新元素 (3)删除 一般情况下,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素 .对于优先权相同的元素,可按先进先出次序处理或按任意优先权

优先级队列实现哈夫曼树的编码和译码

//优先级队列实现的哈夫曼树的编码和译码 #include<iostream> #include<queue> #include<string> using namespace std; class Node { public: float weight; Node* left; Node* right; char ch; Node(float w,Node* l=NULL,Node* r=NULL,char c=' '):weight(w),ch(c),left(l)

stl的优先级队列

#include <iostream> #include <vector> #include <queue> using namespace std; class Timer; typedef Timer* RTimer; class Timer { public: Timer():_interval(0),_expires_time(0){} virtual ~Timer(){} virtual void schedule_timer(int sec,int usec

[算法系列之四]优先级队列

[概念] 优先级队列,顾名思义,就是一种根据一定优先级存储和取出数据的队列.它可以说是队列和排序的完美结合体,不仅可以存储数据,还可以将这些数据按照我们设定的规则进行排序.优先级队列是堆的一种常见应用.有最大优先级队列(最大堆)和最小优先级队列(最小堆).优先级队列是一种维护有一组元素构成的集合S的数据结构. [优先队列支持的基本运算] [cpp] view plaincopy //建立一个保存元素为int的优先级队列,其实是建了一个小顶堆   //但是请特别注意这样的建的堆默认是大顶堆,即我们

link中如何用大根堆小根堆实现优先级队列?是不是需要自己写数据结构?

问题描述 link中如何用大根堆小根堆实现优先级队列?是不是需要自己写数据结构? link中如何用大根堆小根堆实现优先级队列?是不是需要自己写数据结构? 解决方案 参考:http://download.csdn.net/download/Miu__Y/3309472