• 2017 ECJTU ACM 程序设计竞赛


    大厦

    Time Limit : 4000/2000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other)
    Total Submission(s) : 25   Accepted Submission(s) : 7

    Font: Times New Roman | Verdana | Georgia

    Font Size: ← →

    Problem Description

    给你一个n(1<=n<=1000)层楼的大厦,每一楼里面有m(1<=m<=1000)房间,
    每个房间一定的金钱X(1<=x<=1000),假设不同楼层的房间是互通的,相同楼层的房间是不互通的。也就是说每层只能取一个,现在给你一个捡钱的机会。捡钱的方式不同,会导致你得到的钱的不同,求可能捡到的钱的前k大的和

    Input

    输入一个T,表示T组样例;
    每组数据第一行输入n,m,k
    接下来输入n行,每行m个数,代表这个房间拥有的金钱

    Output

    输出可能捡到的钱的前k大的和

    Sample Input

    1
    3 4 5
    1 2 3 4
    5 6 7 8
    1 2 3 4
    

    Sample Output

    75


    题解

    假设任意两层为集合A B(从大到小排序)对于B集合的元素B[i],显然它和A[1]组合值最大,
    如果B[i]+A[j]是前K大值中的一个,那么B[i]+A[k](1<=k < j)必然也是前K大的,
    所以B[i]+A[j]被选则B[i]+A[j-1]之前就被选了,
    所以优先队列中只需维护Size(B)个元素,首先把A[1]+B[i]全部进队,
    每次从队首拿出一个组合(i,j)(表示A[i]+B[j]),把A[i+1]+B[j]进队,
    直到拿出K个元素为止,即为这两个集合合并的前K大
    n层的话只要把每次得到的结果和其他层按照这样处理就可以了


    AC代码
     1 #include <cstdio>
     2 #include <cmath>
     3 #include <cstring>
     4 #include <cstdlib>
     5 #include <iostream>
     6 #include <sstream>
     7 #include <algorithm>
     8 #include <string>
     9 #include <queue>
    10 #include <vector>
    11 using namespace std;
    12 const int maxn= 1005;
    13 const double eps= 1e-6;
    14 const int inf = 0x3f3f3f3f;
    15 typedef long long ll;
    16 int k,n,m;
    17 vector<int> a[maxn];
    18 vector<int> ans,d;
    19 int cmp(int a,int b)
    20 {
    21     return a>b;
    22 }
    23 struct node
    24 {
    25     int i,j,val;
    26     node(){}
    27     node(int i,int j,int val):i(i),j(j),val(val){}
    28     bool operator <(const node &a)const
    29     {
    30         return val<a.val;
    31     }
    32 };
    33 int main()
    34 {
    35     int t;
    36     scanf("%d",&t);
    37     while(t--)
    38     {
    39         scanf("%d %d %d",&n,&m,&k);
    40         int x;
    41         for(int i=1;i<=n;i++)
    42             a[i].clear();
    43         ans.clear();
    44         for(int i=1;i<=n;i++)
    45         {
    46             for(int j=1;j<=m;j++)
    47             {
    48                 scanf("%d",&x);
    49                 a[i].push_back(x);
    50             }
    51             sort(a[i].begin(),a[i].end(),cmp);
    52         }
    53         priority_queue<node> q;
    54         ans.push_back(0);
    55         for(int i=1;i<=n;i++)
    56         {
    57             int x,y,z;
    58             for(int j=0;j<m;j++)
    59             {
    60                 z=a[i][j]+ans[0];
    61                 q.push(node(0,j,z));
    62             }
    63             while(d.size()<k&&!q.empty())
    64             {
    65                 node e=q.top();q.pop();
    66                 d.push_back(e.val);
    67                //printf("%d %d
    ",cnt,d[cnt]);
    68                 //cnt++;
    69                 if(e.i+1<k&&i!=1)
    70                     q.push(node(e.i+1,e.j,ans[e.i+1]+a[i][e.j]));
    71             }
    72             while(!q.empty()) q.pop();
    73             ans.assign(d.begin(),d.end());
    74             d.clear();
    75         }
    76         ll sum=0;
    77         for(int i=0;i<k;i++)
    78             sum+=ans[i];
    79         printf("%lld
    ",sum);
    80     }
    81 }
  • 相关阅读:
    nyoj256-C小加之级数求和
    nyoj254-编号统计
    nyoj286-动物统计
    最长回文子串——manacher
    动态规划:Codeforces Round #427 (Div. 2) C Star sky
    水题:51Nod1432-独木舟
    水题:HDU1716-排列2
    水题:CF16C-Monitor
    数学基础:HUD1124-Factorial(N!末尾0的个数)
    并查集:POJ1182-食物链(并查集比较高端的应用)
  • 原文地址:https://www.cnblogs.com/stranger-/p/7875446.html
Copyright © 2020-2023  润新知