poj 2442 Sequence

Sequence
Time Limit: 6000MS Memory Limit: 65536K
Total 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

1
2 3
1 2 3
2 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 Code

Problem: 2442		Code Length: 1435B
Memory: 604K		Time: 454MS
Language: 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值