zoukankan      html  css  js  c++  java
  • UVA11997求前k个和,多路归并问题

    题意:
         给你一个二维矩阵,n*n的,每次从每一行中拿出来一个,然后加起来组成一个和,一共可以得到n^n个和,要求求出这n^n个和中最小的那n个和。


    思路:
         多路归并问题,先说下多路归并问题,我的理解是有个变量,每个变量都按照自己的变化规律在变化着,每次一旦选用每个变量,那么这个变量就会根据自己的变化规律变化,这种问题我们可以用优先队列来解决,首先我们可以把所有变量都扔进队列,然后在在里面取出一个最小的(或者最大的)作为当前答案,然后把取出来的数值变化后在扔进队列里,如此反复操作,对于这个题目我们可以像白书上一样这样分析,首先我们想一个该问题的简化版,就是给你两个数组,每个数组里面有n个数字,每次从两个数组中任意取出一个数字加起来得到一个和,求前n个最小的和。


    我们可以运用多路归并问题


    A[1]+B[1] <= A[1]+B[2] <= A[1]+B[3]...
    A[2]+B[1] <= A[2]+B[2] <= A[2]+B[3]...
    A[3]+B[1] <= A[3]+B[2] <= A[3]+B[3]...
    ...


    对于每一个集合的每一个变量我们可以这样表示,node.s = A[a] + A[b] ,node.b =b;
    这样这个集合的下一个变量就是 node.s - B[node.b] + B[node.b + 1] ,node.b ++;
    这样说应该没问题吧? 然后我们就开始多路归并,很容易理解和想到,我们直接先把第一列圈放进队列,然后取出一个最为最小的那个,然后把取出的这个的右侧(下一个)放进队列,然后在取,在放,每次都把取出的下一个放进去,执行n此之后就得到了这最小的n个数,这是两个序列的,这个题目是n个序列,这样我们可以吧第一个和第二个合并,然后在用合并的序列去合并第三个,最后把所有的序列都合并,这里说的合并就是前面上多那个多路归并。






    #include<queue>
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>


    #define N 750 + 5


    using namespace std;


    typedef struct NODE
    {
        int s ,b;
        friend bool operator < (NODE a ,NODE b)
        {
           return a.s > b.s;
        }
    }NODE;


    int num[N][N];
    int A[N] ,B[N] ,C[N];
    NODE xin ,tou;




    void duoluguibing(int n)
    {
        priority_queue<NODE>q;  
        for(int i = 1 ;i <= n ;i ++)
        {
           xin.b = 1;
           xin.s = A[i] + B[1];
           q.push(xin);
        }
        for(int i = 1 ;i <= n ;i ++)
        {
            tou = q.top();
            q.pop();
            C[i] = tou.s;
            xin.b = tou.b + 1;
            xin.s = tou.s - B[tou.b] + B[xin.b];
            if(xin.b <= n) q.push(xin);
        }
        return;
    }


    int main ()
    {
        int n ,i ,j;
        while(~scanf("%d" ,&n))
        {
           for(i = 1 ;i <= n ;i ++)
           {
              for(j = 1 ;j <= n ;j ++)
              scanf("%d" ,&num[i][j]);
              sort(num[i] + 1 ,num[i] + n + 1);
           }
           
           
           for(i = 1 ;i <= n ;i ++)
           C[i] = num[1][i];
           for(i = 2 ;i <= n ;i ++)
           {
              for(j = 1 ;j <= n ;j ++)
              A[j] = C[j] ,B[j] = num[i][j];
              duoluguibing(n);
           }
           
           for(i = 1 ;i <= n ;i ++)
           if(i == n) printf("%d " ,C[i]);
           else printf("%d " ,C[i]);
        }
        return 0;
    }
           





  • 相关阅读:
    [转]c++访问python3-实例化类的方法
    【转】利用Boost.Python将C++代码封装为Python模块
    [转]Linux下Python与C++混合编程
    [转]Windows下使用VS2015编译openssl库
    [转]boost::python开发环境搭建
    [转]linux下编译boost.python
    [转]阿里巴巴十年Java架构师分享,会了这个知识点的人都去BAT了
    [转]Python3《机器学习实战》学习笔记(一):k-近邻算法(史诗级干货长文)
    [转]马上2018年了,该不该下定决心转型AI呢
    [转]PostgreSQL命令行使用手册
  • 原文地址:https://www.cnblogs.com/csnd/p/12062566.html
Copyright © 2011-2022 走看看