用到的思想:分组思想
首先考虑只有两个序列的情况
a1 a2 a3 ...... an
b1 b2 b3 ...... bn
ps : a 数组是提前排序的 从小到大
把所有的情况枚举出来
b1+a1, b1+a2, b1+a3,.... b1 + an
b2+a1, b2+a2, b2+a3,.... b2 + an
.................................
bn+a1, bn+a2, bn+a3..... bn + an
第一步 选出最小的数 毫无疑问 最小的是在第一列当中,选出来之后,再选第二小将选中的那个数后面的那个数加入到选择方案中
比如 第一步我们选择的是 b2+a1 那么 在第二步选择第二小的数的时候,就应该把第一列的数 除去 b2+a1 再把b2 + a2 放入选择的所有情况中 再选出最小的数 以此类推 选出在这两个序列中 前 n 小 的数 作为一个新的序列
然后再以此类推将a数组(更新完的操作)与下一个序列进行上一步选择,总共进行m - 1 次操作
PII 第一个存数字 第二个存当前所在下标
#include<bits/stdc++.h> #define pr printf #define sc scanf #define fur(i,a,b) for(int i = a; i<= b ;i++) #define fdr(i,a,b) for(int i = a ;i>=b ;i--) using namespace std; const int N = 2000 + 10 ; int a[N],b[N],c[N]; typedef long long ll; typedef pair<int,int> PII; int n,m; void work() { priority_queue<PII, vector <PII> ,greater <PII> > q; for(int i = 0 ;i < n ; i++){ q.push({ a[0] + b [i] , 0 } ); } for(int i = 0 ;i < n ; i++){ PII t = q.top(); q.pop(); int s = t.first ; int p = t.second ; q.push( {s - a[p] + a[p + 1 ], p + 1 } ); c[i] = s; } for(int i = 0 ;i < n ; i+= 1) a[i] = c[i] ; } int main() { //freopen("in.txt","r",stdin); // m 个序列 每个序列 n 个数 int T ; sc("%d",&T); while(T--){ sc("%d%d",&m ,&n); for(int i = 0 ;i < n; i++){ sc("%d",&a[i]); } sort(a,a+n); for(int i = 0 ; i < m -1 ;i ++){ for(int j = 0 ; j < n ;j ++){ sc("%d",&b[j]); } work(); } for(int i = 0 ; i< n ; i++){ pr("%d ",a[i]); } puts(""); } return 0; }