poj 2442 Sequence

来源:互联网 发布:虚拟机ubuntu怎样重置 编辑:程序博客网 时间:2024/04/30 10:15
Sequence
Time Limit: 6000MS Memory Limit: 65536KTotal Submissions: 8880 Accepted: 2948

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

12 31 2 32 2 3

Sample Output

3 3 4

Source

POJ Monthly,Guang Lin

提示

题意:
给你m(0<m<=100)个序列包含n(0<n<=2000)个正整数。现在每个序列选择一个数并组成一个新的序列,很明显有n^m种序列。现在我们需要计算出这n^m种序列每种序列的数列之和,输出前n个最小的数列之和,你能帮帮我们吗?
思路:
运用优先队列,我们可以维持第一个序列到第二个序列前n个最小的数列之和,之后递推到第n个序列。
a[0]+b[0]<=a[0]+b[1]......<=a[0]+b[n]
a[1]+b[0]<=a[1]+b[1]......<=a[1]+b[n]
......
a[2]+b[0]<=a[2]+b[1]......<=a[2]+b[n]
需要用C++库函数,用数组模拟会超时。(这题貌似正确做法是用堆排序去维护队列,但堆排序不熟用了STL)

示例程序

Source CodeProblem: 2442Code Length: 1435BMemory: 604KTime: 454MSLanguage: G++Result: Accepted#include <cstdio>#include <algorithm>#include <queue>using namespace std;int main(){    int t,n,m,k,a[2000],b[2000],i,i1,i2,i3;    priority_queue<int,vector<int>,less<int> >q;    scanf("%d",&t);    for(i=1;t>=i;i++)    {        scanf("%d %d",&m,&n);        for(i1=0;n>i1;i1++)        {            scanf("%d",&a[i1]);        }        sort(a,a+n);        for(i1=2;m>=i1;i1++)        {            for(i2=0;n>i2;i2++)            {                scanf("%d",&b[i2]);            }            sort(b,b+n);            for(i2=0;n>i2;i2++)            {                q.push(a[i2]+b[0]);//假设b[0]为最小的来看            }            for(i2=1;n>i2;i2++)            {                k=0;//记录有没有一组数据有入队的情况                for(i3=0;n>i3;i3++)                {                    if(a[i3]+b[i2]<q.top())//和顶比较,如果比顶大那么也就没有入队的必要了                    {                        q.pop();                        q.push(a[i3]+b[i2]);                        k=1;                    }                    else                    {                        break;                    }                }                if(k==0)//因为b[]是递增序列,如果当前一个都没入队,后面的也就不可能入队了                {                    break;                }            }            for(i2=n-1;i2>=0;i2--)//计算完转移接着下一组数据            {                a[i2]=q.top();                q.pop();            }        }        printf("%d",a[0]);        for(i1=1;n>i1;i1++)        {            printf(" %d",a[i1]);        }        printf("\n");    }    return 0;}
0 0