题意:n组序列,每组有m个数,从每组数中各选1个,则共有m^n种和,输出最小的前m个和。
题解:优先队列|堆
代码写的太乱了,别看。
用优先队列维护大小为m的最大堆。
先将第一行序列放进队列,同时用数组a[]存优先队列中的m个元素,并升序排序(更快)。队列清空。
接着考虑下一组,对于该组每一个元素x,将a[0]+x放入队列,然后遍历所有组合a[i]+x,维护大小为m的最大堆。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<cmath>
#include<vector>
#include<fstream>
#include<set>
#include<map>
#include<sstream>
#include<iomanip>
#define ll long long
using namespace std;
int t, n, m;
vector<int> a, v, tem;
priority_queue<int> q;
int main() {
scanf("%d", &t);
while (t--) {
a.clear();
scanf("%d%d", &n, &m);
for (int j = 1; j <= m; j++) {
int tt;
scanf("%d", &tt);
a.push_back(tt);
}
sort(a.begin(), a.end());
//for (int i = 0; i < m; i++) q.push(a[i]);
for (int i = 2; i <= n; i++) {
int tt;
v.clear();
for (int j = 1; j <= m; j++) {
scanf("%d", &tt);
v.push_back(tt);
}
for (int j = 0; j < m; j++) {
q.push(v[j] + a[0]);
}
for (int k = 1; k < m; k++) {
for (int j = 0; j < m; j++) {
if (v[j] + a[k] < q.top()) {
q.pop();
q.push(v[j] + a[k]);
}
}
}
a.clear();
while (q.size()) {
a.push_back(q.top());
q.pop();
}
sort(a.begin(), a.end());
}
while (q.size()) a.push_back(q.top()), q.pop();
sort(a.begin(), a.end());
for (int i = 0; i < m; i++) printf("%d ", a[i]);
printf("\n");
}
return 0;
}
堆的做法。
#include <cstdio>
#include <algorithm>
using namespace std;
const int NMax=2100;
int N,M,A[NMax][NMax];
int S1[NMax],S2[NMax],Heap[NMax];
int main() {
int T;
scanf("%d",&T);
while(T--) {
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++)
for(int j=1;j<=M;j++)
scanf("%d",&A[i][j]);
for(int i=1;i<=M;i++) S1[i]=A[1][i];
sort(S1+1,S1+M+1);
for(int i=2;i<=N;i++) {
for(int j=1;j<=M;j++) Heap[j]=A[i][1]+S1[j];
make_heap(Heap+1,Heap+M+1);
for(int j=2;j<=M;j++) {
for(int k=1;k<=M;k++) if(A[i][j]+S1[k]<Heap[1]){
pop_heap(Heap+1,Heap+M+1);
Heap[M]=A[i][j]+S1[k];
push_heap(Heap+1,Heap+M+1);
}
}
for(int j=1;j<=M;j++) S1[j]=Heap[j];
sort(S1+1,S1+M+1);
}
for(int i=1;i<M;i++) printf("%d ",S1[i]);
printf("%d\n",S1[M]);
}
return 0;
}