做多校的时候,大佬说这是一个经典问题。。
k个集合 每个取一个值,求极值。(可以重复取)
不重复的话直接排序 就行qwq,
https://vjudge.net/problem/UVA-11997
看的题解。
http://blog.csdn.net/libin56842/article/details/46446157
我认为在分配的时候,存在一个贪心的思路。
如果求k个最小的,那么就把元素 升序排列,这样每次开始都得加的最小的,这样可以保证第一个肯定是最小的,当确定一个最小的之后,让这个a换一个b相加,看能否是次小的。(加其他的都比他大)。依次类推。
如果求最大值,那么就开始升序排列,然后求最大的。
#include <iostream>
#include <cstdio>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int maxn=2000;
/*多路归并排序。参考的博客
首先我们考虑双路归并排序的特点,
然后 ,俺们就可以维护一个 二元组。
这个二元组叫
1 a[1]+b[1],a[1]+b[2],a[1]+b[3],,,,a[1]+b[n]
2 a[2]+b[1] ,a[2]+b[2],,,,,
n
维护这么多就好了,B(s,m) s就是和,s=a[www.baidu.com]+b[m];
*/
int a[maxn][maxn];
int m;
struct Node{
int w,r;
Node(int _a,int _b){w=_a;r=_b;}
friend bool operator < (Node a, Node b)
{
return a.w>b.w; //x小的优先级高。
}
};
bool cmp2(int a,int b){
return a>b;
}
void merge(int *a,int *b,int *c)
{
int i,j,k;
priority_queue<Node> Q;
for(i = 0;i<m;i++)
Q.push(Node(a[i]+b[0],0));
for(i = 0;i<m;i++)//只取最小的n个
{
Node r = Q.top();
Q.pop();
c[i] = r.w;
int i = r.r;
if(i+1<m)
{
Q.push(Node(r.w-b[i]+b[i+1],i+1));
}
}
}
int main()
{
while(~scanf("%d",&m)){
for(int i=0;i<m;i++){
for(int j=0;j<m;j++)
scanf("%d",&a[i][j]);
sort(a[i],a[i]+m);
}
for(int i=1;i<m;i++){
merge(a[0],a[i],a[0]);
}
printf("%d",a[0][0]);
for(int i=1;i<m;i++)
printf(" %d",a[0][i]);
cout<<"\n";
}
return 0;
}