做这个题首先思考两个问题
由这两个得出,要求n个数组每个数组m个值,数组1和数组2的和找出最小的m个,再用来和数组3求和,找到最小的m个,最终得到所有的数组中的最小的m个
由于每个数组都是有序的,而且我们要求的最小的m个,数组a[i][j]+队列中的值 > 队首的值,那么a[i][j]加上队列中以后的值都会大于队首,对于我们要求解的最小的m个值无意义。队列中保存了当前数组到之前所有数组的最小的m个和,不断更新队列
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
int a[110][2100] , b[2100] ;
priority_queue <int> p ;
int main()
{
int i , j , k , n , m , t ;
scanf("%d", &t);
while(t--)
{
scanf("%d %d", &n, &m);
for(i = 0 ; i < n ; i++)
{
for(j = 0 ; j < m ; j++)
scanf("%d", &a[i][j]);
sort(a[i],a[i]+m);
}
for(i = 0 ; i < m ; i++)
p.push(a[0][i]) ;
for(i = 1 ; i < n ; i++)
{
for(j = 0 ; j < m ; j++)
{
b[j] = p.top();
p.pop();
}
for(j = 0 ; j < m ; j++)
{
for(k = m-1 ; k >= 0 ; k--)
{
if(j == 0)
p.push( a[i][j]+b[k] );
else
{
if( a[i][j] + b[k] < p.top() )
{
p.pop();
p.push(a[i][j]+b[k]);
}
else
break;
}
}
}
}
for(j = 0 ; j < m ; j++)
{
b[j] = p.top();
p.pop();
}
for(j = m-1 ; j >= 0 ; j--)
{
if(j == 0)
printf("%d\n", b[j]);
else
printf("%d ", b[j]);
}
}
return 0;
}