uva11997

C - K Smallest Sums

题意:

  给出k个数组,从每个数组中任意挑选出一个元素,将这些数相加后得到一个和,输出前k小的和。

分析:

  首先考虑两个数组时,直接用k^2的循环求出所有的和,通过优先队列找出前k小的和。当有三个数组a,b,c时,用a,b求出的和做新数组,与c做循环求出和,推广到k个数组时,也是这样两两求和。

  这样算的话,时间肯定会超时的,但是考虑一下,我们需要用到所有的和吗,因为求的是前k小的和,所以我们每次只需要保留前k小的和就好了。

代码:

#include <map>
#include <queue>
#include <vector>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>

using namespace std;
#define ll long long
#define ull unsigned long long
#define cls(x) memset(x,0,sizeof(x))
#define clslow(x) memset(x,-1,sizeof(x))

const int maxn=800;

int a[maxn][maxn];

struct Item {
    int s,b;
    Item(int s,int b):s(s),b(b) {}
    bool operator < (const Item& rhs) const {
        return s>rhs.s;
    }
};

//合并两个数组
void Merge(int* A,int * B,int *C,int n)
{
    priority_queue<Item>que;

    for(int i=1;i<=n;i++){
        que.push(Item(A[i]+B[1],1));
    }
    for(int i=1;i<=n;i++){
        Item item=que.top();que.pop();
        C[i]=item.s;
        int b=item.b;
        //加入A[a]+B[b+1]
        if(b<n) que.push(Item(item.s-B[item.b]+B[item.b+1],b+1));
    }
}

int main()
{
//    freopen("in.txt","r",stdin);
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                scanf("%d",&a[i][j]);
            }
            sort(a[i]+1,a[i]+n+1);
        }

        //两两合并
        for(int i=2;i<=n;i++){
            Merge(a[1],a[i],a[1],n);
        }

        for(int i=1;i<=n;i++){
            if(i>1) printf(" ");
            printf("%d",a[1][i]);
        }
        printf("\n");
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/shutdown113/p/9345534.html