Uva11997 K Smallest Sums

本文介绍了一种使用优先队列解决多个数组中寻找k个最小元素和的问题的方法。通过两两归并的方式,最终实现时间复杂度为O(k^2*logk)的高效算法。示例输入输出展示了算法的有效性和正确性。

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

题目: You’re given k arrays, each array has k integers. There are kk ways to pick exactly one element in each array and calculate the sum of the integers. Your task is to find the k smallest sums among them.
Input
There will be several test cases. The first line of each case contains an integer k (2 ≤ k ≤ 750). Each of the following k lines contains k positive integers in each array. Each of these integers does not exceed 1,000,000. The input is terminated by end-of-file (EOF).
Output
For each test case, print the k smallest sums, in ascending order. Sample Input 3 1 8 5 9 2 5 10 7 6 2 1 1 1 2 Sample Output 9 10 12 2 2
【多路归并问题】
要用优先队列logk
k个序列,k个数,两两归并
时间复杂度O(k^2*logk)

#include<iostream>
#include<cstdio>
#include<ctime>
#include<algorithm>
#include<queue>
using namespace std;
const int N=760;
int n,A[N],B[N];
inline int readin(){
    int res = 0;
    char ch;
    while((ch = getchar())>'9'||ch <'0');
    res= ch-'0';
    while((ch = getchar())>='0'&&ch <='9')
        res= res* 10+ch -'0';
    return res;
}
struct ii{
    int s,b;
    ii(int s = 0,int b =0):s(s),b(b){ }
    bool operator <(const ii &a)const {
        if(s^a.s)return s>a.s;
    }
};//a[1]+b[1]<a[1]+b[2]……,b 有序的,s=a[i]+b[j] ->s'=s-b[j]+b[j+1],只需要存储s,b
void merge(){//two merge
    priority_queue<ii>q;
    for(int i = 1; i<= n;i++)
        q.push(ii(A[i]+B[1],1));
    for(int i = 1; i<= n;i++)//push n min into C[N]
    {
        ii tmp=q.top();
        q.pop();
        A[i]=tmp.s;
        int b =tmp.b;
        if(b+1<=n)q.push(ii(tmp.s-B[b]+B[b+1],b+1));//贪心的思维,,取当前最小的下一个
    }//最多n-1次,所以如果一直在一个序列,最多可能有一次会多余
}
int main(){
    freopen("Uva.in","r",stdin);
    freopen("Uva.out","w",stdout);
    while((scanf("%d",&n)==1)&&n){
            for(int i = 1; i<= n;i++)
            A[i]=readin();
            sort(A+1,A+n+1);
            for(int o=2; o <= n; o++){
                for(int i = 1; i<= n;i++)
                B[i]=readin();
                sort(B+1,B+n+1);
                merge();//指针传值再到A数组
            }
            printf("%d",A[1]);
            for(int i = 2; i<= n;i++)
            printf(" %d",A[i]);
            printf("\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值