UVA11997求前k个和,多路归并问题
题意:
给你一个二维矩阵,n*n的,每次从每一行中拿出来一个,然后加起来组成一个和,一共可以得到n^n个和,要求求出这n^n个和中最小的那n个和。
思路:
多路归并问题,先说下多路归并问题,我的理解是有个变量,每个变量都按照自己的变化规律在变化着,每次一旦选用每个变量,那么这个变量就会根据自己的变化规律变化,这种问题我们可以用优先队列来解决,首先我们可以把所有变量都扔进队列,然后在在里面取出一个最小的(或者最大的)作为当前答案,然后把取出来的数值变化后在扔进队列里,如此反复操作,对于这个题目我们可以像白书上一样这样分析,首先我们想一个该问题的简化版,就是给你两个数组,每个数组里面有n个数字,每次从两个数组中任意取出一个数字加起来得到一个和,求前n个最小的和。
我们可以运用多路归并问题
A[1]+B[1] <= A[1]+B[2] <= A[1]+B[3]...
A[2]+B[1] <= A[2]+B[2] <= A[2]+B[3]...
A[3]+B[1] <= A[3]+B[2] <= A[3]+B[3]...
...
对于每一个集合的每一个变量我们可以这样表示,node.s = A[a] + A[b] ,node.b =b;
这样这个集合的下一个变量就是 node.s - B[node.b] + B[node.b + 1] ,node.b ++;
这样说应该没问题吧? 然后我们就开始多路归并,很容易理解和想到,我们直接先把第一列圈放进队列,然后取出一个最为最小的那个,然后把取出的这个的右侧(下一个)放进队列,然后在取,在放,每次都把取出的下一个放进去,执行n此之后就得到了这最小的n个数,这是两个序列的,这个题目是n个序列,这样我们可以吧第一个和第二个合并,然后在用合并的序列去合并第三个,最后把所有的序列都合并,这里说的合并就是前面上多那个多路归并。
#include<queue>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 750 + 5
using namespace std;
typedef struct NODE
{
int s ,b;
friend bool operator < (NODE a ,NODE b)
{
return a.s > b.s;
}
}NODE;
int num[N][N];
int A[N] ,B[N] ,C[N];
NODE xin ,tou;
void duoluguibing(int n)
{
priority_queue<NODE>q;
for(int i = 1 ;i <= n ;i ++)
{
xin.b = 1;
xin.s = A[i] + B[1];
q.push(xin);
}
for(int i = 1 ;i <= n ;i ++)
{
tou = q.top();
q.pop();
C[i] = tou.s;
xin.b = tou.b + 1;
xin.s = tou.s - B[tou.b] + B[xin.b];
if(xin.b <= n) q.push(xin);
}
return;
}
int main ()
{
int n ,i ,j;
while(~scanf("%d" ,&n))
{
for(i = 1 ;i <= n ;i ++)
{
for(j = 1 ;j <= n ;j ++)
scanf("%d" ,&num[i][j]);
sort(num[i] + 1 ,num[i] + n + 1);
}
for(i = 1 ;i <= n ;i ++)
C[i] = num[1][i];
for(i = 2 ;i <= n ;i ++)
{
for(j = 1 ;j <= n ;j ++)
A[j] = C[j] ,B[j] = num[i][j];
duoluguibing(n);
}
for(i = 1 ;i <= n ;i ++)
if(i == n) printf("%d\n" ,C[i]);
else printf("%d " ,C[i]);
}
return 0;
}
UVA11997求前k个和,多路归并问题的更多相关文章
- 两个序列求前k大和
---恢复内容开始--- 没有题目,没有题意,这是学长提过的一个技巧,给你两个排好序的序列,每次可以各从中取一个,求前k大的和, 一个优先队列,先将a序列中最大的那个和b序列所有元素相加存进队列中,每 ...
- BZOJ2006:超级钢琴(ST表+堆求前K大区间和)
Description 小Z是一个小有名气的钢琴家,最近C博士送给了小Z一架超级钢琴,小Z希望能够用这架钢琴创作出世界上最美妙的音乐. 这架超级钢琴可以弹奏出n个音符,编号为1至n.第i个音符的美妙度 ...
- 算法导论学习之线性时间求第k小元素+堆思想求前k大元素
对于曾经,假设要我求第k小元素.或者是求前k大元素,我可能会将元素先排序,然后就直接求出来了,可是如今有了更好的思路. 一.线性时间内求第k小元素 这个算法又是一个基于分治思想的算法. 其详细的分治思 ...
- 牛客第六场 J.Heritage of skywalkert(On求前k大)
题目传送门:https://www.nowcoder.com/acm/contest/144/J 题意:给一个function,构造n个数,求出其中任意两个的lcm的最大值. 分析:要求最大的lcm, ...
- HDU 6041 I Curse Myself(点双联通加集合合并求前K大) 2017多校第一场
题意: 给出一个仙人掌图,然后求他的前K小生成树. 思路: 先给出官方题解 由于图是一个仙人掌,所以显然对于图上的每一个环都需要从环上取出一条边删掉.所以问题就变为有 M 个集合,每个集合里面都有一堆 ...
- 隐式Dijkstra:在状态集合中用优先队列求前k小
这种技巧是挺久以前接触的了,最近又突然遇到几道新题,于是总结了一下体会. 这种算法适用的前提是,标题所述的"状态集合"大到不可枚举(否则枚举就行了qaq) ...
- D - K Smallest Sums(多路归并+贪心)
Problem K K Smallest Sums You're given k arrays, each array has k integers. There are kk ways to pic ...
- HDU - 6041:I Curse Myself(Tarjan求环&K路归并)
There is a connected undirected graph with weights on its edges. It is guaranteed that each edge app ...
- [csu/coj 1080]划分树求区间前k大数和
题意:从某个区间内最多选择k个数,使得和最大 思路:首先题目给定的数有负数,如果区间前k大出现负数,那么负数不选和更大,于是对于所有最优选择,负数不会出现,所以用0取代负数,问题便转化为区间的前k大数 ...
随机推荐
- MySQL全面瓦解24:构建高性能索引(策略篇)
学习如果构建高性能的索引之前,我们先来了解下之前的知识,以下两篇是基础原理,了解之后,对面后续索引构建的原则和优化方法会有更清晰的理解: MySQL全面瓦解22:索引的介绍和原理分析 MySQL全面瓦 ...
- 数据库索引知识到MySQL InnoDB
前言 本文聊聊数据库中的索引,涉及索引基础数据结构,分类.以及使用索引的缺点. 索引就像一本书的目录,商场里面各个楼层指示图,让我们不需要自己无目的的找,而是能够很快的找到自己想要的. 1. 索引的基 ...
- Ubuntu更换python默认版本
设置python版本: 1 sudo update-alternatives --install /usr/bin/python python /usr/bin/python2 100 2 sudo ...
- 关于Java中Collections.sort和Arrays.sort的稳定性问题
一 问题的提出 关于Java中Collections.sort和Arrays.sort的使用,需要注意的是,在本文中,比较的只有Collections.sort(List<T> ele ...
- BZOJ_2243 [SDOI2011]染色 【树链剖分+线段树】
一 题目 [SDOI2011]染色 二 分析 感觉树链剖分的这些题真的蛮考验码力的,自己的码力还是不够啊!o(╯□╰)o 还是比较常规的树链剖分,但是一定记得这里的线段树在查询的时候一定要考虑链于链相 ...
- HYSBZ 1734 二分
传送门 题面: 农夫 John 建造了一座很长的畜栏,它包括N (2 <= N <= 100,000)个隔间,这些小隔间依次编号为x1,...,xN (0 <= xi <= 1 ...
- 5行代码!完成bat病毒制作!!!
这个病毒的功能是删除当前目录下.cpp类型的代码. copy %0 "%userprofile%\AppData\Roaming\Microsoft\Windows\Start Menu\P ...
- 平方十位数(蓝桥杯第八届国赛真题 JAVA-B组)
思路:从大到小枚举,判断其平方是否不重复 答案:9814072356 //水题 标题:平方十位数 由0~9这10个数字不重复.不遗漏,可以组成很多10位数字. 这其中也有很多恰好是平方数(是某个数的平 ...
- 攻防世界 reverse 666
666 2019_UNCTF main int __cdecl main(int argc, const char **argv, const char **envp) { char myen; / ...
- [差分][二分][贪心]luogu P3634 [APIO2012]守卫
题面 https://www.luogu.com.cn/problem/P3634 给m个限制,可以是一段区间中必须有或者必须无忍者 最多有k个忍者,问有多少个位点一定有忍者 分析 首先用差分标记一下 ...