二叉树--Sequence--利用优先队列贪心求解最优匹配

本文介绍了一个算法问题,即从多个数字序列中选择元素组成新序列并找到这些序列和的最小n个值。通过使用优先队列来高效地解决这个问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

超链接:Sequence

Description

给定m个数字序列,每个序列包含n个非负整数。我们从每一个序列中选取一个数字组成一个新的序列,显然一共可以构造出n^m个新序列。接下来我们对每一个新的序列中的数字进行求和,一共会得到n^m个和,请找出最小的n个和

Input
输入的第一行是一个整数T,表示测试用例的数量,接下来是T个测试用例的输入
每个测试用例输入的第一行是两个正整数m(0 < m <= 100)和n(0 < n <= 2000),然后有m行,每行有n个数,数字之间用空格分开,表示这m个序列
序列中的数字不会大于10000
Output
对每组测试用例,输出一行用空格隔开的数,表示最小的n个和
Sample Input
1
2 3
1 2 3
2 2 3
Sample Output
3 3 4


=================================================================================================================================

分析:维护一个长度为n的优先队列,每次输入后都对前n个最小和进行更新,m-1次迭代后得到最终的前n个最小和。

起初想了好久都不知道怎么用二叉树写,最后参考了别人的程序用了优先队列,虽然没有练习到二叉树的底层操作,但是练了下优先队列的应用也是可以的。

这里比较尴尬的情况是,看了别人的程序,然后根据别人的思路把题做出来后,是标明原创还是标明转载呢?貌似都感觉怪怪的。或许这就是某些同学不用csdn博客的原因吧。

#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;

const int maxn = 2005;
int t,m,n,a[maxn],b[maxn];
priority_queue<int> q;//利用a维护前n个最小和

int main()
{
	scanf("%d",&t);
	while(t--) {
	    scanf("%d%d",&m,&n);
	    for (int i = 0; i < n; ++i) scanf("%d",&a[i]);sort(a,a+n);	//a存储前n个最小和
	    m--;
	    while(m--) {
	        for (int i = 0; i < n; ++i) scanf("%d",&b[i]);sort(b,b+n);
	        for (int i = 0; i < n; i++) q.push(a[i]+b[0]);	//生成长度为n的优先队列
	        for (int i = 1; i < n; ++i)	{	//计算剩余的组合,并更新队列
	        	int j;
	        	for (j = 0; j < n; ++j)
	        		if(b[i]+a[j]<q.top()) q.pop(),q.push(b[i]+a[j]);//a剪枝
	        		else break;
	        	if(j == 0) break;//b剪枝,b[i]+a[0]都不行,那b[i+1]+a[0]或b[i]+a[1]也不行
	        }	
	        for (int i = n-1; i >= 0; i--) a[i] = q.top(),q.pop();	//为下次更新作准备
	    }
		for (int i = 0; i < n; i++) printf("%d%c",a[i],i == n-1?'\n':' ');
	}
	return 0;
}

参考:http://blog.youkuaiyun.com/m0_37975647/article/details/77898419

ps:用dp貌似也行,懒得看了。现在重点是二叉树。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值