zoukankan      html  css  js  c++  java
  • uva 11997 K Smallest Sums

    https://vjudge.net/problem/UVA-11997

    题意:

    给出k个数组,每个数组中有k个元素,要求从每个数组中选择一个元素相加得到的K^K个数中选择最小的k个并输出。

    思路:

    如果直接模拟,那么就是k^k的复杂度,显然是不能接受的。。。

    首先看有两个数组的情况,先把A,B两个数组排序,把每一个A数组中的元素加B[0]  和    B[0]的下标     保存在一个结构体当中,扔进一个优先队列,

    这个优先队列的优先级是sum小为队首(求的是最小值)。

    之后从0到k - 1枚举,每次从优先队列中取一个元素,那么当前的sum肯定是最小的,于是记录,之后看看这个结构体保存的下标,如果小于K - 1的话,

    那么就把sum - B[id].sum + B[id+1].sum和id+1丢进优先队列。这一步实际就保证了优先队列的队首始终是最小的元素并且元素不会重复加。

    因为第一个比B[id].sum大的元素就是B[id+1].sum,所以sum - B[sum]实际是当前的A[i].sum,因为B[id].sum已经用过了,所以B[id+1].sum + A[i].sum进队就保证了当前队列中的k个元素一定是最小的。

    那么K个数组,其实每次读入一个合并一次就好了。

    这叫多路归并问题(不懂

    具体还是结合代码理解,能手算理解一下更好!

    代码:

     1 #include <stdio.h>
     2 #include <queue>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 struct node
     7 {
     8     long long sum;
     9     int b;
    10 
    11     bool operator < (const node& rhs) const
    12     {
    13         return rhs.sum < sum;
    14     }
    15 };
    16 
    17 node a[755],c[755];
    18 
    19 int k;
    20 
    21 void unit(void)
    22 {
    23     priority_queue<node> pq;
    24 
    25     while (!pq.empty()) pq.pop();
    26 
    27     for (int i = 0;i < k;i++)
    28     {
    29         pq.push(node{a[i].sum + c[0].sum,0});
    30     }
    31 
    32     for (int i = 0;i < k;i++)
    33     {
    34         a[i].sum = pq.top().sum;
    35         int id = pq.top().b;
    36 
    37         pq.pop();
    38 
    39         if (id < k - 1)
    40         {
    41             pq.push(node{a[i].sum - c[id].sum + c[id+1].sum,id + 1});
    42         }
    43 
    44     }
    45 }
    46 
    47 bool cmp(node aa,node bb)
    48 {
    49     return aa.sum < bb.sum;
    50 }
    51 
    52 int main()
    53 {
    54 
    55 
    56     while (scanf("%d",&k) != EOF)
    57     {
    58         for (int i = 0;i < k;i++)
    59         {
    60             scanf("%lld",&a[i].sum);
    61         }
    62 
    63         for (int i = 1;i < k;i++)
    64         {
    65             for (int j = 0;j < k;j++)
    66             {
    67                 scanf("%lld",&c[j].sum);
    68             }
    69 
    70             sort(a,a+k,cmp);
    71             sort(c,c+k,cmp);
    72 
    73             for (int j = 0;j < k;j++) c[j].b = j;
    74 
    75             unit();
    76         }
    77 
    78         sort(a,a+k);
    79 
    80         for (int i = k - 1;i >= 0;i--)
    81         {
    82             printf("%d%c",a[i].sum,i == 0 ? '
    ' : ' ');
    83         }
    84     }
    85 
    86     return 0;
    87 }
  • 相关阅读:
    ps中的一些方法
    extjs 横向滚动条 和 本地排序
    JS JSON.parse() 和 JSON.stringify()
    SQL 同一个表中 根据一列更新另一列(不同行)
    extjs2.2 panel加背景色
    extjs2.2 combo的监听
    ExtJS2.2 form表单提交时不提交emptyText
    Extjs 复制对象
    Extjs 显示或隐藏滚动条
    Extjs2.2 开始时间,结束时间,工期 联动(选二补一),包含日期,天数的互转
  • 原文地址:https://www.cnblogs.com/kickit/p/7681186.html
Copyright © 2011-2022 走看看