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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值