#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
//#define INPUT
using namespace std;
/**
Problem:POJ2442 - Sequence
Begin Time : 2nd/March/2012 1:00 p.m.
End Time: 2nd/March/2012 4:14 p.m
Cost Time: 3H 14Min
看的别人的解题报告过的,非常感谢
http://hi.baidu.com/%C0%B6%C9%ABarch/blog/item/f9d343f49cd92e53d7887d73.html
的博主!
思路:
我们要找到n个smallest的数,用贪心法可以解决这一问题。
(1)维护两个数组,a和b,以及一个大根堆p
循环不变式:
(1)初始化
将元素读入a,将a排序(从小到大)
执行并重复(2)
(2)保持
对于这全部数据第二行到第m行(从第二行开始,因为第一行读到a里了)
将元素读入b,将b排序(从小到大)
For i = 0 to n -1
heap.push(a[i]+b[0]);
然后
for(int i = 1; i < n;i++)
{
for(int j = 0 ; j < n; j++)
{
if( (b[i] + a[j]) > heap.top() ) break;
heap.pop(); ///从heap中删除一个最大的元素,从而保证heap中元素数目不变
heap.push(b[i] + a[j]);
}
}
/这样,就选出了n个最小值
然后把heap中的n个值按照从小到大给
a[1] -> a[n],并将heap清空。
执行(2)
(3)最终结果
输出a中全部元素就可以了,注意,对于每个case都要换行哦!
*/
bool comp(int a,int b)
{
return b > a;
}
int main(int argc,char* argv[])
{
#ifdef INPUT
freopen("b:\\acm\\poj2442\\input.txt","r",stdin);
#endif
int T;
scanf("%d",&T);
for(int i = 0 ; i < T; i++)
{
int m = 0 , n = 0;
vector<int> a;vector<int> b;
priority_queue<int> h_heap;
a.clear();b.clear();
int buf = 0;
scanf("%d%d",&m,&n);
for(int j = 0 ; j < n; j++)
{
scanf("%d",&buf);
a.push_back(buf);
}
sort(&a[0],&a[0]+n,comp);
for(int z = 0 ; z < m - 1; z++)
{
b.clear();
for(int j = 0 ; j < n; j++)
{
scanf("%d",&buf);
b.push_back(buf);
}
sort(&b[0],&b[0]+n,comp);
for(int j = 0; j < n; j++)
{
h_heap.push(a[j]+b[0]);
}
///这时候b已经选过了;
for(int j = 1; j < n; j++)
{
for(int k = 0 ; k < n ; k++)
{
if ( b[j] + a[k] > h_heap.top() )
{
break;
}
else
{
h_heap.pop();
h_heap.push(b[j]+a[k]);
}
}
}
//这时候已经选出来该两行的n个最小值了
for(int j = 0; j < n; j++)
{
a[ n - 1 - j ] = h_heap.top();
h_heap.pop();
}
//copy回去,把a
}
for(int j = 0 ; j < n; j++)
{
printf("%d ",a[j]);
}
printf("\n");
}
return 0;
}