Description
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个数字.从每行均取出一个数字相加,共有m^n个解,输出解最小的n个.
题解:建一个大根堆,先将第一行的全部扔进去,在全部扔回一个数组里,那么此时数组中的数是从大到小排列的.
然后这个数组,我们给它中的每一个数取出,再加上第二行的第一个数,全部扔进堆里,接着对于第2~n个数中的每一个,我们将它与数组中最小的,次小的……(数组倒过来)相加,如果和比大根堆的堆顶大,这就是我们要找的了,将堆顶弹出,将这个值插入.然而我并不知道这玩意的复杂度,居然就这么A了?真是奇怪,有信仰的话可一定要用手写堆啊!
代码如下:
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define hi puts("hi"); using namespace std; int map[105][2005]; struct Heap { int a[300010],sz; void init() { sz=1; } void add(int x) { int now=sz++; while(now>1) { int fa=now>>1; if(a[fa]>x) { break; } a[now]=a[fa]; now=fa; } a[now]=x; } int pop() { int ans=a[1]; int now=1; int x=a[--sz]; while((now<<1)<sz) { int ls=now<<1,rs=now<<1|1; if(a[ls]<a[rs]&&rs<sz) { ls=rs; } if(a[ls]<x) { break; } a[now]=a[ls]; now=ls; } a[now]=x; return ans; } int top() { return a[1]; } int empty() { return sz==1; } } heap; int main() { int t; scanf("%d",&t); while(t--) { int m,n,b[200010],cnt=0; heap.init(); scanf("%d%d",&m,&n); for(int i=1; i<=m; i++) { for(int j=1; j<=n; j++) { scanf("%d",&map[i][j]); } } for(int i=1; i<=n; i++) { heap.add(map[1][i]); } for(int i=2; i<=m; i++) { cnt=0; while(!heap.empty()) { b[++cnt]=heap.pop(); } for(int j=1; j<=cnt; j++) { heap.add(b[j]+map[i][1]); } for(int j=2; j<=n; j++) { for(int k=cnt; k>=1; k--) { if(b[k]+map[i][j]<heap.top()) { heap.pop(); heap.add(b[k]+map[i][j]); } else { break; } } } } cnt=0; while(!heap.empty()) { b[++cnt]=heap.pop(); } for(int i=cnt; i>=2; i--) { printf("%d ",b[i]); } printf("%d ",b[1]); } }