POJ 2442 Sequence(堆的应用)

Sequence

Time Limit: 6000MS

 

Memory Limit: 65536K

Total Submissions: 4906

 

Accepted: 1490

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

 解题报告:这道题的题意是给我们m, n,下面有m行,每行有n个数,让我们求出前n个最小组合的和,共有n ^ m种的组合,但是只是让我们求出前n组即可,思路就是利用堆的性质,在遍历求和的同时调整堆;用的是STL写的

代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAX = 2010;
int a[MAX], b[MAX], heap[MAX];
int main()
{
    int i, j, m, n, t, flag;
    scanf("%d", &t);
    while (t --)
    {
        scanf("%d%d", &m, &n);
        for (i = 0; i < n; ++i)
        {
            scanf("%d", &a[i]);
        }
        sort(a, a + n);//将数组a按从小到大排序
        while (-- m)
        {
            for (i = 0; i < n; ++i)
            {
                scanf("%d", &b[i]);
            }
            sort(b, b + n);//将数组b按从小到大排序
            for (i = 0; i < n; ++i)
            {
                heap[i] = a[i] + b[0];
            }
            make_heap(heap, heap + n);//make_heap 是按照给定的排序准则,把“最大”的元素排列到首位,而其他元素看上去并非有序:
            //相当于建立大顶堆
            // 例如:输入 5个数 2 4 6 5 3 经历操作是 6 5 4 2 3
            for (i = 1; i < n; ++i)
            {
                flag = 0;
                for (j = 0; j < n; ++j)
                {
                    int temp = b[i] + a[j];
                    if (temp < heap[0])
                    {
                        //pop_heap()不是真的把最大(最小)的元素从堆中弹出来。而是重新排序堆
                        //它把0和i个元素交换,然后将[0,i)的数据再做成一个大顶堆堆。
                        pop_heap(heap, heap + n);
                        heap[n - 1] = temp;
                        //push_heap()假设由[0,i)是一个有效的堆,
                        //然后,再把堆中的新元素加进来,做成一个堆。
                        push_heap(heap, heap + n);
                        flag = 1;
                    }
                    else
                    {
                        break;//当前已经是最小了
                    }
                }
                if (flag == 0)
                {
                    break;//已经求出前n个最小的组合的和了
                }
            }
            for (i = 0; i< n; ++i)
            {
                a[i] = heap[i];
            }
            sort(a, a + n);//重新排序
        }
        for (i = 0; i < n - 1; ++i)
        {
            printf("%d ", a[i]);
        }
        printf("%d\n", a[n - 1]);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/lidaojian/p/2441311.html