Sequence
Time Limit: 6000MS | Memory Limit: 65536K | |
Total Submissions: 7697 | Accepted: 2543 |
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
Source
POJ Monthly,Guang Lin
关于堆和堆排序,请看我的文章:http://www.ihypo.net/1648.html
#include <stdio.h>
#include <string.h>
#include <algorithm>
int s1[2010];//建立堆用的数组
int s2[2010];//输入数的数组
int s3[2010];//第一次输入用,后面都是当临时数组用
void adjust(int len,int i)//堆的调整函数
{
int mx = i;
int lt = mx << 1;
int rt = mx << 1 | 1;
while(lt <= len || rt <= len)
{
if(lt <= len && s1[lt] > s1[mx])
mx = lt;
if(rt <= len && s1[rt] > s1[mx])
mx = rt;
if(mx != i)
{
int tmp = s1[mx];
s1[mx] = s1[i];
s1[i] = tmp;
i = mx;
lt = mx << 1;
rt = mx << 1 | 1;
}
else
break;
}
}
void build(int len)//建立堆的函数
{
for(int i = len >> 1; i >= 1; i--)
adjust(len,i);
}
void sortheap(int len)//堆排序函数
{
while(len)
{
int tmp = s1[1];
s1[1] = s1[len];
s1[len] = tmp;
len--;
adjust(len,1);
}
}
int main()
{
int m,n,t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&m,&n);
for(int i = 1; i <= n; i++)
{
scanf("%d",&s3[i]);
s1[i] = s3[i];//这一操作是用来防止只有一行数的
}//先把第一组数据读入
if(m == 1)
build(n);//如果只有一行数的话,那么这行数从小到大排序就是答案,这里建立堆,后面sortheap排序,就可以输出了
for(int i = 1; i < m; i++)
{
for(int j = 0; j < n; j++)
{
scanf("%d",&s2[j]);//读入数据,放入数s2中
}
std::sort(s2,s2 + n);//对s2排序
for(int j = 1; j <= n; j++)
s1[j] = s3[j] + s2[0];//s2[0]是s2中最小的一个,让s3加上它,就保证当前最小
build(n);//建最大堆
for(int j = 1; j <= n; j++) //这两个循环使用来找当前前n个最小值加上新来的s2的值是否有比最大堆的堆顶小的,如果有,更新最大堆堆顶,否则,跳出
{
for(int k = 1; k < n; k++)
{
if(s3[j] + s2[k] < s1[1])
{
s1[1] = s3[j] + s2[k];
adjust(n,1);
}
else
break;
}
}
for(int j = 1; j <= n; j++)
s3[j] = s1[j];//把堆中在线更新的的前n个最小值赋值给s3,下次循环还要用
}
sortheap(n);//堆排序
for(int i = 1; i <= n; i++)
{
printf("%d",s1[i]);
if(i <= n - 1)
printf(" ");
}
printf("\n");
}
return 0;
}