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


      题目大意 有k个长度为k的数组,从每个数组中选出1个数,再把这k个数进行求和,问在所有的这些和中,最小的前k个和。

      考虑将前i个数组合并,保留前k个和。然后考虑将第(i + 1)个数组和它合并,保留前k个和。

      如果暴力的话就进行就暴力枚举每一对,然后进行求和,然后再选出前k个,然而这样会TLE。

      可以考虑将另外一个数组进行排序。然后可以看做是k个已经排好序的数组进行归并

    {A[1] + B[1], A[1] + B[2], ...}
    {A[2] + B[1], A[2] + B[2], ...}
    {A[3] + B[1], A[3] + B[2], ...}
    .
    .
    .
    {A[k] + B[1], A[k] + B[2], ...}

      对于每个数组,只有前一个值被取了,后一个值才有可能被取。

      所以用一个优先队列进行维护,先将所有数组的第一个元素放进去,然后每次取出一个元素,再将它的后一个放入队列。

      每次合并时间复杂度O(klogk),所以总时间复杂度为O(k2logk)

    Code

     1 /**
     2  * UVa
     3  * Problem#11997
     4  * Accepted
     5  * Time: 190ms
     6  */
     7 #include <bits/stdc++.h>
     8 using namespace std;
     9 typedef bool boolean;
    10 
    11 int k;
    12 int A[751], B[751], C[751];
    13 int *X, *Y;
    14 
    15 typedef class Item {
    16     public:
    17         int x, b;
    18         
    19         Item(int x = 0, int b = 0):x(x), b(b) {        }
    20         
    21         boolean operator < (Item xb) const {
    22             return X[x] + B[b] > X[xb.x] + B[xb.b];
    23         }
    24         
    25         int getVal() {
    26             return X[x] + B[b];
    27         }
    28 }Item;
    29 
    30 inline void merge() {
    31     priority_queue<Item> que;
    32     for(int i = 0; i < k; i++)
    33         que.push(Item(i, 0));
    34     
    35     for(int i = 0; i < k; i++) {
    36         Item e = que.top();
    37         que.pop();
    38         Y[i] = e.getVal();
    39         que.push(Item(e.x, e.b + 1));
    40     }
    41     while(!que.empty())    que.pop();
    42     swap(X, Y);
    43 }
    44 
    45 inline boolean init() {
    46     if(scanf("%d", &k) == EOF)    return false;
    47     X = A, Y = C;
    48     for(int i = 0; i < k; i++)
    49         scanf("%d", X + i);
    50     sort(A, A + k);
    51     for(int i = 1; i < k; i++) {
    52         for(int j = 0; j < k; j++)
    53             scanf("%d", B + j);
    54         sort(B, B + k);
    55         merge();
    56     }
    57     return true;
    58 }
    59 
    60 inline void solve() {
    61     for(int i = 0; i < k - 1; i++)
    62         printf("%d ", X[i]);
    63     printf("%d
    ", X[k - 1]);
    64 }
    65 
    66 int main() {
    67     while(init()) {
    68         solve();
    69     }
    70     return 0;
    71 }
  • 相关阅读:
    位图 与矢量图对比
    用ocam工具录视频及转换视频 ffmpeg
    教学设计-饭后百步走
    教学设计例--跟小猴子一起玩
    教学设计-妈妈跳舞
    教学设计--Scratch2.0入门介绍
    Scratch2.0在线注册用户并使用帮助
    下载Scratch2.0离线版并安装教程
    把Sratch作品转为swf文件
    跟小猴子开心玩
  • 原文地址:https://www.cnblogs.com/yyf0309/p/7797202.html
Copyright © 2011-2022 走看看