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; }