UVA11997-多路归并排序-K Smallest Sums

来源:互联网 发布:飞机大战java代码框架 编辑:程序博客网 时间:2024/05/29 18:07

做多校的时候,大佬说这是一个经典问题。。
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;}