uva11997 K Smallest Sums

<span style="font-family: Arial, Helvetica, sans-serif;">// #pragma comment(linker, "/STACK:1024000000,1024000000")</span>
/*
题意:有K个整数数组,包含K个元素。在每个数组中取一个元素加起来,可以得到k^k个和。
求这些和中最小的K个值
分析:这题有简化版本的,即2个整数数组A,B,包含K个元素,在每个数组中取一个元素加起
来,可以得到k^2个和,求这些和中最小的K个值。我们需要把这k^2个和组织成如下k个有序表.
表1:A1+B1<=A1+B2<=......<=A1+Bk
表2: A2+B1<=A2+B2<=......<=A2+Bk
表k:Ak+B1<=AK+B2<=......<=Ak+Bk
我们可以用二元组(s,b)来表示一个元素即s=Aa+Bb;为什么不保存A的下标a呢?因为我们用
不到a的值。如果我们需要元素(s,b)在表a的下一个元素(s',b+1).
只需要计算s'=s+B[b+1]-B[b];
这样我们先将K个表的第一个元素压入优先队列,这样队列中就用k个元素了。然后从队列中出
一个值,就压入这个值所在表的下一个元素,直到k个值都出了优先队列。
这样就得到k个最小值了。。
然后对与K个数组。我们只需两两合并即可。
*/
#include <iostream>
#include <algorithm>
#include <iomanip>
#include <sstream>
#include <string>
#include <stack>
#include <queue>
#include <deque>
#include <vector>
#include <map>
#include <set>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <limits.h>
// #define DEBUG
#ifdef DEBUG
#define debug(...) printf( __VA_ARGS__ )
#else
#define debug(...)
#endif
#define MEM(x,y) memset(x, y,sizeof x)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> ii;
const int inf = 1 << 30;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
int G[760][760];
struct Item{
    int s, b;
    Item(int s,int b){
        this->s = s;
        this->b = b;
    }
    bool operator < (const Item& rhs)const{
        return this->s > rhs.s;
    }
};
int k;
int res[760];
void merge(int* A,int* B,int *C){
    int cnt = 0;
    priority_queue<Item> que;
    for (int i = 0;i < k;i++)
        que.push(Item(A[i] + B[0],0));
    while(!que.empty()){
        Item tmp = que.top();
        que.pop();
        C[cnt++] = tmp.s;
        if (tmp.b + 1 < k) 
            que.push(Item(tmp.s + (B[tmp.b+1] - B[tmp.b]),tmp.b+1));
        if (cnt == k) break;
    }
}
int main()
{    
    // freopen("in.txt","r",stdin);
    // freopen("out.txt","w",stdout);
    while(~scanf("%d",&k)){
        for (int i = 0;i < k;i++){
            for (int j = 0;j < k;j++)
                scanf("%d",&G[i][j]);
            sort(G[i],G[i]+k);
        }
        memcpy(res,G[0],sizeof res);
        for (int i = 1;i < k;i++){
            merge(res,G[i],res);
            // for (int i = 0;i < k;i++)
                // printf("%d ",res[i]);
            // printf("\n");
        }
        for (int i = 0;i < k;i++){
            if (i == 0) printf("%d",res[i]);
            else printf(" %d",res[i]);
        }
        puts("");
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值