POJ2442 Sequence【k小堆问题】

本文介绍了一种算法,用于从一个m行n列的数值矩阵中选取每行一个数构成序列,共n^m种可能的序列,进而找到序列和最小的n个序列组合。文章详细解释了算法步骤,包括使用优先队列来维护最小序列和的方法。

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

题目大意是:m行n列的一个数矩阵,每行抽一个数,可以同列,那么有n^m种sequence组合,在这些sequence中,找出:sequence和最小的n个sequence组合

方法:

当行数大于等于2行时候

       先比较第一行和第二行的和,把较小的放在第一行,把第一行压入优先队列

行数只有1行的时候,不进行该操作,直接把第一行的数压入优先队列(否则会造成第二行是0行和第一行交换后,把0行压入优先队列,wa掉)

 

对接下来的第2行到第m行

        先把优先队列输入到一个数组a里面,并把优先队列清空,a是从大到小的,那么接下来的遍历都是倒序遍历

        排序该行,然后该行第一个数和a中所有数相加压入优先队列

        对该行的第二个到第n个数每个数,和a里面每个数相加,如果比优先队列最大的元素小,那么弹出最大元素,压入该元素,比最大元素大,则break,跳到该行的下一个数

 

最后输出结果问题,最后一个数不要带空格,只能带回车符

#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[1111][2222];
int a[2222];
int main()
{
	#ifndef ONLINE_JUDGE
		freopen("G:/1.txt","r",stdin);
		freopen("G:/2.txt","w",stdout);
	#endif
	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]);
	}
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值