K Smallest Sums uva+优先队列

K Smallest Sums

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). The size of input file does not exceed 5MB.

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

Output for the Sample Input

9 10 12
2 2
解决方案:就如白书上所说,当为两两列数组A、B时,且A、B排序可得:
表1:A0+B0<=A0+B1<=A0+B2.......
表2:A1+B0<=A1+B1<=A1+B2.......
表3:A2+B0<=A2+B1<=A2+B2.......
可推的公式:s=A[b]+B[b],s`=A[b]+B[b+1],s`=A[b]+B[b]-B[b]+B[b+1],可得s'=s-B[b]+B[b+1];这样子的话就不用下标b了,只要入优先队列的时候存一下下标b,等下次出队的时候,可用b推出下一个值。然而本题是多维的,所以,可以两个两个的来。
代码:
#include<iostream>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
struct node{
  int s,b;
  node(int A,int B):s(A),b(B){}
  bool operator< (const node &a)const{

       return s>a.s;
  }

};

void Sum(int* A,int* B,int *C,int n){
 priority_queue<node > Q;
 for(int i=0;i<n;i++){
    Q.push(node(A[i]+B[0],0));
 }
 for(int i=0;i<n;i++){
    node temp=Q.top();
    Q.pop();
    C[i]=temp.s;
    int b=temp.b;
    if(b+1<n) Q.push(node((temp.s-B[b]+B[b+1]),b+1));
 }

}
int matrix[755][755];
int main(){
    int n;
    while(~scanf("%d",&n)){
        for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            scanf("%d",&matrix[i][j]);
        }
        sort(matrix[i],matrix[i]+n);
        }
        for(int i=1;i<n;i++){
            Sum(matrix[0],matrix[i],matrix[0],n);///为什么这里可以再把值赋回matrix[0]呢?因为matrix[0]只是在形成第一批初始值的时候用到,在出队推出下一个值得时候没有用到。
        }
         for(int i=0;i<n;i++){
    printf("%d%c",matrix[0][i],i==n-1?'\n':' ');
    }

   }





    return 0;}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值