POJ-2442 Sequence(优先队列)
2018-03-19 01:13
411 查看
Given m sequences, each contains n non-negative integer. Now we may select one number from each sequence to form a sequence with m integers. It’s clear that we may get n ^ m this kind of sequences. Then we can calculate the sum of numbers in each sequence, and get n ^ m values. What we need is the smallest n sums. Could you help us?
Input
The first line is an integer T, which shows the number of test cases, and then T test cases follow. The first line of each case contains two integers m, n (0 < m <= 100, 0 < n <= 2000). The following m lines indicate the m sequence respectively. No integer in the sequence is greater than 10000.
Output
For each test case, print a line with the smallest n sums in increasing order, which is separated by a space.
Sample Input
1
2 3
1 2 3
2 2 3
Sample Output
3 3 4
题意:有m个数列,每个数列n个值,每个序列中选取一个值可以组成n^m种不同的序列,求前n小的序列和。
用两个优先队列维护前n小和。首先将第一列n个数字放入从大到小的优先队列中,每次弹出一个最小值和下一行的每个元素相加,并放入另一个从小到大的优先队列中,当放满n个值时,每次求和结果先和队列中的top对比,若小于top则弹出并塞入这个和,否则舍弃这个较大和。这样维护的就是求和到第i行时的前n小序列和。当数列中n个元素都和下一列的元素求和完后,将这些前n小和又倒出来塞入从大到小的队列中,这样就和一开始对第一行的数列一样,每次选取一个最小值进行和后面的值求和,并将和塞入从小到大的优先队列中,这样反复倒腾最后加和到最后一行时仍然是所有数列求和的最小值,然后放入从大到小的数列中,依次弹出即是升序输出。
Input
The first line is an integer T, which shows the number of test cases, and then T test cases follow. The first line of each case contains two integers m, n (0 < m <= 100, 0 < n <= 2000). The following m lines indicate the m sequence respectively. No integer in the sequence is greater than 10000.
Output
For each test case, print a line with the smallest n sums in increasing order, which is separated by a space.
Sample Input
1
2 3
1 2 3
2 2 3
Sample Output
3 3 4
题意:有m个数列,每个数列n个值,每个序列中选取一个值可以组成n^m种不同的序列,求前n小的序列和。
用两个优先队列维护前n小和。首先将第一列n个数字放入从大到小的优先队列中,每次弹出一个最小值和下一行的每个元素相加,并放入另一个从小到大的优先队列中,当放满n个值时,每次求和结果先和队列中的top对比,若小于top则弹出并塞入这个和,否则舍弃这个较大和。这样维护的就是求和到第i行时的前n小序列和。当数列中n个元素都和下一列的元素求和完后,将这些前n小和又倒出来塞入从大到小的队列中,这样就和一开始对第一行的数列一样,每次选取一个最小值进行和后面的值求和,并将和塞入从小到大的优先队列中,这样反复倒腾最后加和到最后一行时仍然是所有数列求和的最小值,然后放入从大到小的数列中,依次弹出即是升序输出。
#include<stdio.h>///两个优先队列组合使用 #include<queue> using namespace std; int main() { int t,i,j,m,n,num; scanf("%d",&t); while(t--) { scanf("%d%d",&m,&n); priority_queue<int ,vector<int>,less<int> >s;///一个优先级 从 小->大 priority_queue<int ,vector<int>,greater<int> >q;///一个优先级 从 大->小 for(i=1; i<=m; i++)///输入m列 { if(i==1)///先将第一列作为基础塞入q队列中 { for(j=0; j<n; j++) { scanf("%d",&num); q.push(num); } } else { int numd[n+10],sum; for(j=0; j<n; j++)///几列,存入一个数组中 { scanf("%d",&numd[j]); } while(q.size())///从q队列中,一个一个选出元素,分别与后面输入的数组中的每一个值相加 { sum=q.top();///选出队首元素,记为sum q.pop();///出列 for(j=0; j<n; j++)///和输入的数组中每个都加一遍 { if(s.size()==n&&s.top()>sum+numd[j])///若超过或等于了n个元素,判断s队列中的队首(放入队列中的最大值)是否大于当前选出的数和数组中元素之和 { s.pop();///若大于,弹出那个较大数,重新塞入求和而得的较小的数 s.push(sum+numd[j]); } else if(s.size()<n)///s队列中若没达到n个元素,加完就塞进去 { s.push(sum+numd[j]); } }///这样一个循环下来,就将下一组数与当前q队列中的某一个元素相加完毕,并筛选出了前n个较小的求和数 }///while的下一轮将求和队列中的下一个数,并继续筛选求和数中的前n小值 while(s.size())///所有数筛选完毕此时在s队列中都是最小的前n个数 { q.push(s.top()); s.pop(); }///每行完成更新后将求和结果统一塞回Q队列中准备下一行筛选求和 } } while(q.size()) { printf("%d%c",q.top(),(q.size()-1==0)?'\n':' '); q.pop(); } } return 0; }
相关文章推荐
- poj 2442 Sequence(优先队列)
- POJ 2442 Sequence(优先队列)
- POJ 题目2442 Sequence(技巧,优先队列)
- POJ 2442 Sequence(优先队列)
- poj 2442 Sequence
- POJ 2442 Sequence (STL优先队列)
- poj 2442 Sequence
- POJ 2442 Sequence
- poj 2442 Sequence 优先队列的运用
- POJ 2442 Sequence
- POJ 2442Sequence
- poj 2442 Sequence (Priority Queue)
- poj 2442 Sequence(堆)
- POJ-2442 Sequence (K路归并问题拓展)
- POJ 2442 Sequence
- POJ 2442 Sequence (堆)
- POJ 2442 Sequence (手写堆)
- poj 2442 -- Sequence
- poj 2442 Sequence