zoukankan      html  css  js  c++  java
  • UVA 11997 K个最小和

    UVA 11997

    【题目描述】:给定k组数,每组k个数,从每组数中各取出一个数,然后把他们加和,在不的加和组合中,求其中的最小的k的数。K<=750

    【算法分析】:K个最小和

    【思路分析】:刚刚拿到这道题,感觉难以下手。所以先分析最朴素的算法。决策方案,k^k种,太大了。如果想先计算,再排序,空间上都不能存储。我们再分析题目条件,发现只要求出前K小的数。然后分析,我们现在手上有效的工具sort,如果对每一维排序,复杂度是5*10^7,说实话,我开始时觉得这个也很大了,但是如果不将所有的排序,假设有一维数据全是极小数,就悲剧了。现在我们得到的是k维全部从小到大排序的数字。因为只需要k个最小值,对于前两组,有用信息是两数加和的最小值,保留k个即可。经过k-1次求最小即可。精髓是优先队列实现,只要有k个当前最小出队就可以了。当a[i]+b[i]被选定为当前最小时,a[i]+b[i+1]可能试下一个最小数。

    【完整代码】:

      1 //核心在于二路归并算法O(n)的复杂度,
      2 
      3 //而且只要求局部最优解,k个最小
      4 
      5 #include<iostream>
      6 
      7 #include<stdio.h>
      8 
      9 #include<string.h>
     10 
     11 #include<algorithm>
     12 
     13 #include<stdlib.h>
     14 
     15 #include<math.h>
     16 
     17 #include<queue>
     18 
     19 #include<vector>
     20 
     21 #include<map>
     22 
     23 #define MAXN 755+10
     24 
     25 #define MAXM 20000+5
     26 
     27 #define oo 9556531
     28 
     29 #define eps 0.000001
     30 
     31 #define PI acos(-1.0)//这个精确度高一些
     32 
     33 #define REP1(i,n) for(int i=0;i<(n);i++)
     34 
     35 #define REP2(i,n) for(int i=1;i<=(n);i++)
     36 
     37 using namespace std;
     38 
     39  
     40 
     41 int A[MAXN][MAXN];
     42 
     43 int n;
     44 
     45 struct Table
     46 
     47 {
     48 
     49     int x;
     50 
     51     int y;
     52 
     53     int cal;//表示A[i]+B[j]
     54 
     55     bool operator<(const Table& x) const{
     56 
     57         return cal>x.cal;
     58 
     59     }
     60 
     61 };
     62 
     63 void merge(int A[],int B[])//合并A,B,再存储到A中
     64 
     65 {
     66 
     67     priority_queue<Table> T;
     68 
     69     int C[MAXN];
     70 
     71 for(int i=0;i<n;i++)
     72 
     73 //构建A[0]+B[0],A[0]+B[1],......A[0]+B[n-1]
     74 
     75     {
     76 
     77         Table nt=(Table){0,i,A[0]+B[i]};
     78 
     79         T.push(nt);
     80 
     81     }
     82 
     83     int cnt=0;
     84 
     85     while (cnt<n)
     86 
     87     {
     88 
     89         Table nt=T.top();
     90 
     91         T.pop();
     92 
     93         C[cnt++]=nt.cal;
     94 
     95         if (nt.x+1>=n) continue;
     96 
     97         nt=(Table){nt.x+1,nt.y,A[nt.x+1]+B[nt.y]};
     98 
     99         T.push(nt);
    100 
    101     }
    102 
    103     for(int i=0;i<n;i++) A[i]=C[i];
    104 
    105 }
    106 
    107 int main()
    108 
    109 {
    110 
    111     while(cin>>n)
    112 
    113     {
    114 
    115         for(int i=0;i<n;i++)
    116 
    117         {
    118 
    119             for(int j=0;j<n;j++) cin>>A[i][j];
    120 
    121             sort(A[i],A[i]+n);//750*750*7,有超时危险
    122 
    123         }
    124 
    125         for(int i=1;i<n;i++)
    126 
    127         merge(A[0],A[i]);//将A[0]和A[i],存储在A[0]
    128 
    129         cout<<A[0][0];
    130 
    131         for(int i=1;i<n;i++) cout<<" "<<A[0][i];
    132 
    133         cout<<endl;
    134 
    135     }
    136 
    137     return 0;
    138 
    139 }

     

    【关键词】:局部解,优先队列。

  • 相关阅读:
    iOS代码段整理
    Git命令行
    Vue开发系列四- 网络请求库vue-resource的使用
    Vue开发系列三 调试
    Vue开发系列三-打包
    Vue开发系列二 熟悉项目结构
    错误及经验记录
    cocopods sh 项目运行权限问题
    关于添加UITextField添加输入内容判定导致九宫格键盘无法使用问题
    catagory添加属性
  • 原文地址:https://www.cnblogs.com/little-w/p/3525292.html
Copyright © 2011-2022 走看看