Sequence(POJ2442 k小堆问题)

Sequence
Time Limit: 6000MS Memory Limit: 65536K
Total Submissions: 10071 Accepted: 3321

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

题意:每行中取一个数,求和。取最小的n个和。
堆的使用还有很多玄妙,尚未领悟。
#include <cstdio>  
#include <cstdlib>  
#include <iostream>  
#include <algorithm>  
#include <cstring>  
#include <cmath>  
#include <queue>  
using namespace std;
priority_queue<int>que;
int m, n;
int num[110][2200];
int a[2200];
int main()
{ 
	int T;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%d%d", &m, &n);
		for (int i = 1; i <= m; i++)
		{
			for (int j = 1; j <= n; j++)
			{
				scanf("%d", &num[i][j]);
			}
		}
		if (m >= 2)
		{
			int sum1 = 0, sum2 = 0;
			for (int i = 1; i <= n; i++)
				sum1 += num[1][i];
			for (int i = 1; i <= n; i++)
				sum2 += num[2][i];
			if (sum1>sum2)
				swap(num[1], num[2]);
		}
		for (int i = 1; i <= n; i++)
		{
			que.push(num[1][i]);
		}
		for (int i = 2; i <= m; i++)
		{
			sort(num[i] + 1, num[i] + 1 + n);
			for (int j = 1; j <= n; j++)
			{
				a[j] = que.top();
				que.pop();
			}
			for (int j = 1; j <= n; j++)
			{
				que.push(num[i][1] + a[j]);
			}
			for (int j = 2; j <= n; j++)
			{
				for (int k = n; k >= 1; k--)
					if (num[i][j] + a[k]<que.top())
					{
						que.pop();
						que.push(num[i][j] + a[k]);
					}
					else
					{
						break;
					}
			}
		}
		for (int i = 1; i <= n; i++)
		{
			a[i] = que.top();
			que.pop();
		}
		for (int i = n; i >= 2; i--)
		{
			printf("%d ", a[i]);
		}
		printf("%d\n", a[1]);
	}
}
转载地址:http://blog.csdn.net/u011775691/article/details/28644411

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值