题目大意 有k个长度为k的数组,从每个数组中选出1个数,再把这k个数进行求和,问在所有的这些和中,最小的前k个和。

  考虑将前i个数组合并,保留前k个和。然后考虑将第(i + 1)个数组和它合并,保留前k个和。

  如果暴力的话就进行就暴力枚举每一对,然后进行求和,然后再选出前k个,然而这样会TLE。

  可以考虑将另外一个数组进行排序。然后可以看做是k个已经排好序的数组进行归并

{A[] + B[], A[] + B[], ...}
{A[] + B[], A[] + B[], ...}
{A[] + B[], A[] + B[], ...}
.
.
.
{A[k] + B[1], A[k] + B[], ...}

  对于每个数组,只有前一个值被取了,后一个值才有可能被取。

  所以用一个优先队列进行维护,先将所有数组的第一个元素放进去,然后每次取出一个元素,再将它的后一个放入队列。

  每次合并时间复杂度O(klogk),所以总时间复杂度为O(k2logk)

Code

 /**
* UVa
* Problem#11997
* Accepted
* Time: 190ms
*/
#include <bits/stdc++.h>
using namespace std;
typedef bool boolean; int k;
int A[], B[], C[];
int *X, *Y; typedef class Item {
public:
int x, b; Item(int x = , int b = ):x(x), b(b) { } boolean operator < (Item xb) const {
return X[x] + B[b] > X[xb.x] + B[xb.b];
} int getVal() {
return X[x] + B[b];
}
}Item; inline void merge() {
priority_queue<Item> que;
for(int i = ; i < k; i++)
que.push(Item(i, )); for(int i = ; i < k; i++) {
Item e = que.top();
que.pop();
Y[i] = e.getVal();
que.push(Item(e.x, e.b + ));
}
while(!que.empty()) que.pop();
swap(X, Y);
} inline boolean init() {
if(scanf("%d", &k) == EOF) return false;
X = A, Y = C;
for(int i = ; i < k; i++)
scanf("%d", X + 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();
}
return true;
} inline void solve() {
for(int i = ; i < k - ; i++)
printf("%d ", X[i]);
printf("%d\n", X[k - ]);
} int main() {
while(init()) {
solve();
}
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个值,每次从一组中选一个,共K^k种,问前K个小的. 思路:优先队列处理多路归并,每个状态含有K个元素.详见刘汝佳算法指南. #include<iostream> #i ...

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

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

  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】优先级队列

    来自<训练指南>优先级队列的例题. 题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18702 题意:给定 ...

  7. 【UVA–11997 K Smallest Sums 】

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

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

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

  9. uva_11997,K Smallest Sums优先队列

    #include<iostream> #include<cstdio> #include<cstring> #include<queue> #inclu ...

随机推荐

  1. 网络编程之Socket详解

    在说socket之前.我们先了解下相关的网络知识: 端口   在Internet上有很多这样的主机,这些主机一般运行了多个服务软件,同时提供几种服务.每种服务都打开一个Socket,并绑定到一个端口上 ...

  2. 使用mysqlbinlog从二进制日志文件中查询mysql执行过的sql语句 (原)

    前提MySQL开启了binlog日志操作1. 查看MySQL是否开启binlog(进mysql操作) mysql> show variables like 'log_bin%';       2 ...

  3. 关于c语言中的program_invocation_short_name

    错误源自用g++的交叉编译工具链编译eudev.经过一番查找,发现在 errno.h 这个头文件中有 program_invocation_short_name 的 extern 定义. 经过查看 e ...

  4. Rpgmakermv(18)GALV RollCredits

    原文: Galv's Roll Credits ---------------------------------------------------------------------------- ...

  5. 原生js实现图片轮播效果

    思路:设置父容器(一定宽度,一定高度,相对定位,子容器超出部分进行隐藏),子容器图片并排(浮动,绝对定位,每次点击进行相应的左或右偏移量) 1.html: <!DOCTYPE html> ...

  6. python2.7之乱码问题

    python 3之后当然不存在乱码问题了.python 2的乱码问题有时就有点头疼了.(代码均为在windows下测试) 示例:保存为test1.py 报错信息如下: 解决办法: 我将代码保存为tes ...

  7. JavaScript--元素对象方法setAttribute() 和appendChild()

    appendChild() 方法可向节点的子节点列表的末尾添加新的子节点 setAttribute() 方法创建或改变某个新属性.如果指定属性已经存在,则只设置该值 <!DOCTYPE html ...

  8. Palindrome Bo (预处理 + 区间DP)

    先进行离散化,然后再预处理出所有位置的下一个元素,做好这一步对时间的优化非常重要. 剩下的就是一般的DP了.区间DP #include<bits/stdc++.h> using names ...

  9. linux 命令杂集

    [1]查找日志中某个字符串XXXX tail -f  日志文件名 |  grep  "XXXX" [2]linux抓包命令 tcpdump -i XXX -A  ip xxx.xx ...

  10. Linux基础命令---join

    join 找出两个文件中相同的字段,根据相同字段合并两个文件,将合并结果显示到标准输出. 此命令的适用范围:RedHat.RHEL.Ubuntu.CentOS.SUSE.openSUSE.Fedora ...