K个最小和(K Smallest Sums,UVA-11997 )多路归并

10 篇文章 0 订阅
4 篇文章 0 订阅

题目链接

https://vjudge.net/problem/UVA-11997

题意

给定k个数组,每个数组有k个值。从每个数组中选一个值,然后对所选值累加求和。问这k^k个和中最小的k个分别是多少。将其升序输出。

分析

参考自刘汝佳《白书》中解法:多路归并。

先考虑简化情况:k=2.k=2时,和有k^2个,将这k^2个元素排序后,前k个即为所求。
多路归并是归并排序的升级版。
算法过程:
将k^2个和分成k个有序数组,每个数组有k个元素。用优先队列来维护每个数组中的最小值,通过k次出队、入队就可以得到最终结果。

对于k>2的情况,两两合并即可。

代码

#include <bits/stdc++.h>
using namespace std;

const int maxn=760;

struct node
{
    int sum,p;
    //node(int sum,int p):sum(sum),p(p){}
    bool operator<(const node &o)const
    {
        return sum>o.sum;
    }

};
void merge(int *a,int *b,int *c,int n)
{
    priority_queue<node> que;
    for(int i=0;i<n;i++)
        que.push(node{a[i]+b[0],0});
    for(int i=0;i<n;i++)
    {
        node t=que.top();que.pop();
        c[i]=t.sum;
        if(t.p+1<n) que.push(node{t.sum-b[t.p]+b[t.p+1],t.p+1});
    }
}
int ac[maxn][maxn];
int main()
{
    int k;
    while(cin>>k)
    {
        for(int i=0;i<k;i++)
            for(int j=0;j<k;j++)
            cin>>ac[i][j];
        for(int i=0;i<k;i++)
            sort(ac[i],ac[i]+k);
        for(int i=1;i<k;i++)
            merge(ac[0],ac[i],ac[0],k);
        for(int i=0;i<k;i++)
        {
            if(i) cout<<" "<<ac[0][i];
            else cout<<ac[0][i];
        }
        cout<<endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值