这是从刘汝佳训练指南上找的例题,值得学习的地方就是要养成把问题拆分然后再多路归并的好习惯,题目是要求从k组数据中任意取一个数找出然后选出其中和最小的k组数据,选择最小可以用优先队列很快实现,那么如何选择就应该想想选择呢?按书上思路就是先把问题分成只有两组数据时的情况,那么列式就变成:
A1+B1<A1+B2<A1+B3....
A2+B1<A2+B2<A3+B3....
.
AN+B1<AN+B2<AN+B3...
那么这样以来我们每次选出最优的就可以了,然后把其去掉再比较再选择就可以了。
#include<stdio.h>
#include<stdlib.h>
#include<queue>
#include<algorithm>
using namespace std;
struct Item{
int s;
int p;
bool operator <(const Item&temp) const{
return s > temp.s;
}
};
int a[800];
int b[800];
int k;
void combine(int*A,int*B,int*C){
priority_queue<Item>q;
for(int i=0;i<k;i++){
Item item;
item.s=A[i]+B[0];
item.p=0;
q.push(item);
}
for(int i=0;i<k;i++){
Item item;
item=q.top();
q.pop();
A[i]=item.s;
if(item.p+1<k){
item.s=item.s-B[item.p]+B[item.p+1];
item.p+=1;
q.push(item);
}
}
}
int main(){
while(scanf("%d",&k)==1){
for(int i=0;i<k;i++)scanf("%d",&a[i]);//先读取第一排的数
sort(a,a+k);
for(int i=1;i<k;i++){
for(int i=0;i<k;i++)scanf("%d",&b[i]);//读取后面k-1排的数
sort(b,b+k);
combine(a,b,a);
}
printf("%d",a[0]);
for(int i=1;i<k;i++)printf(" %d",a[i]);
printf("\n");
}
return 0;
}