zoukankan      html  css  js  c++  java
  • Poj2442 Sequence 贪心+堆优化

    本人水平有限,题解不到为处,请多多谅解

    本蒟蒻谢谢大家观看

    题目传送门

    推荐博客

    翻译如下:

    问题E:Poj2442序列

    描述

    给定M个长度为N的序列,从每个序列中任取一个数求和,可以构成N ^ M个和,求其中最小的N个和
    。N≤2000,M≤100。

    输入项

    第一行是整数T,它表示测试用例的数量,然后是T个测试用例。 
    每种情况的第一行都包含两个整数m,n(0 <m <= 100,0 <n <= 2000)。 
    以下m行分别表示m序列。 
    序列中没有整数大于10000。

    输出量

    对于每个测试用例,以递增的顺序打印n个总和最小的行,并用空格隔开。

    样本输入

    1 
    2 3 
    1 2 3 
    2 2 3

    样本输出

    3 3 4



    注意:每一个数只能用一次

    对于2个序列,我们可以先把这两个序列从小到大排序,然后用第一个序列的第一项分别去加第二个序列的各项,得到n个和,放到一个优先队列(大根堆)中;
    接下来用第一序列的第二项分别去加第二序列的各项,如果和小于优先队列的首项,那么首项出队,新的和入队,否则结束对第一序列第二项的操作,转而操作第一序列第三项;
    如此进行直到操作完第一序列的所有项,得到了第一第二序列各项相加的前n小的和。

    那么对于3个序列的问题,我们可以先用上述方法合并前两个序列,得到一个n项的序列,再和第三序列合并出答案。
    依次类推即可

    要先对每一列进行排序,再根据以上进行操作,当且仅当队列不为空时,把最优解传递下去。

    注意:防止PE,注意格式。


    code:
     
     1 #include<bits/stdc++.h>
     2 #pragma GCC optimize(3)
     3 using namespace std;
     4 int m,n;
     5 int T;
     6 int f[105][2005];
     7 priority_queue<int> q;
     8 inline int read(){
     9     int x=0,f=1;char ch=getchar();
    10     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    11     while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    12     return x*f;
    13 }
    14 int main()
    15 {    
    16     T=read();
    17     while(T--)
    18     {
    19         m=read(),n=read();
    20         for(int i=1;i<=m;i++){
    21             for(int j=1;j<=n;j++)
    22                 f[i][j]=read();
    23             sort(f[i]+1,f[i]+1+n);//按照每一列的序列从小到大排序 
    24         }
    25         for(int i=1;i<m;i++){
    26             for(int j=1;j<=n;j++){
    27                 q.push(f[i][1]+f[i+1][j]);//第一列的第一个+之后每一列的值 
    28             }
    29             for(int j=2;j<=n;j++){
    30                 for(int k=1;k<=n;k++){//第一列的第二个+之后每一列值 打擂台
    31                     if(f[i][j]+f[i+1][k]>=q.top())   break;
    32                     else{
    33                         q.pop();
    34                         q.push(f[i][j]+f[i+1][k]);
    35                     }
    36                 }
    37             }
    38             int hhh=n;
    39             while(!q.empty()){
    40                 f[i+1][hhh]=q.top();//因为是大根堆,所以对顶存储在最后一个 
    41                 q.pop();//不断合并两个序列 
    42                 hhh--;//依次类推 
    43             }
    44         }
    45         for(int i=1;i<=n;i++){
    46             if(i!=1){
    47                 printf(" ");//注意格式
    48             }
    49             printf("%d",f[m][i]);//因为不断合并时最优解是一直传递下来的
    50         }
    51         printf("
    ");
    52     }
    53     return 0;
    54 }

    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。

    什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。
    人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。

    来自博主Bolgggggg



  • 相关阅读:
    RSS Reader in PC & iPhone
    Implementation Notes: Runtime Environment Map Filtering for Image Based Lighting
    A implementaion for 2D blue noise
    Specular Aliasing与Specular Leaking
    PBR Metallic/Roughness工作流中Albedo与F0的计算方法
    Mathematica .nb程序运行不下去的原因
    关于ddx/ddy重建法线在edge边沿上的artifacts问题
    make: 警告:检测到时钟错误。您的创建可能是不完整的。
    C++ 变长模板参数
    CMake set 语法
  • 原文地址:https://www.cnblogs.com/nlyzl/p/11724676.html
Copyright © 2011-2022 走看看