• 济南学习 Day 3 T3 am


    选数字 (select)
    Time Limit:3000ms Memory Limit:64MB
    题目描述
    LYK 找到了一个 n*m 的矩阵,这个矩阵上都填有一些数字,对于第 i 行第 j 列的位置上
    的数为 ai,j。
    由于它 AK 了 noip2016 的初赛,最近显得非常无聊,便想到了一个方法自娱自乐一番。
    它想到的游戏是这样的: 每次选择一行或者一列, 它得到的快乐值将会是这一行或者一列的
    数字之和。之后它将该行或者该列上的数字都减去 p(之后可能变成负数) 。如此,重复 k
    次,它得到的快乐值之和将会是它 NOIP2016 复赛比赛时的 RP 值。
    LYK 当然想让它的 RP 值尽可能高,于是它来求助于你。
    输入格式(select.in)
    第一行 4 个数 n,m,k,p。
    接下来 n 行 m 列,表示 ai,j。
    输出格式(select.out)
    输出一行表示最大 RP 值。
    输入样例
    2 2 5 2
    1 3
    2 4
    输出样例
    11
    数据范围
    总共 10 组数据。
    对于第 1,2 组数据 n,m,k<=5。
    对于第 3 组数据 k=1。
    对于第 4 组数据 p=0。
    对于第 5,6 组数据 n=1,m,k<=1000。
    对于第 7,8 组数据 n=1,m<=1000,k<=1000000。
    对于所有数据 1<=n,m<=1000,k<=1000000,1<=ai,j<=1000,0<=p<=100。
    样例解释
    第一次选择第二列,第二次选择第二行,第三次选择第一行,第四次选择第二行,第五
    次选择第一行,快乐值为 7+4+2+0+-2=11。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<queue>
     5 using namespace std;
     6 #define INF 100000000000000LL
     7 #define ll long long
     8 #define R register
     9 priority_queue<int> q1,q2;
    10 ll xx[1000100],yy[1000100],x[1100],y[1100];
    11 ll n,m,k,p,ans;
    12 void anwser()
    13 {
    14     xx[0]=0;yy[0]=0;
    15     for(ll i=1;i<=n;i++)
    16       q1.push(x[i]);
    17     for(ll i=1;i<=k;i++)
    18     {
    19         R ll t=q1.top();
    20         xx[i]=xx[i-1]+t;
    21         q1.pop();
    22         q1.push(t-p*m);
    23     }
    24     for(int j=1;j<=m;j++)
    25       q2.push(y[j]);
    26     for(ll i=1;i<=k;i++)
    27     {
    28         R ll t=q2.top();
    29         yy[i]=yy[i-1]+t;
    30         q2.pop();
    31         q2.push((t-p*n));
    32     }
    33     ans=-INF;
    34     for(int i=1;i<=k;i++)
    35       ans=max(ans,xx[i]+yy[k-i]-p*(k-i)*i);
    36     
    37 }
    38 int main()
    39 {
    40     scanf("%d%d%d%d",&n,&m,&k,&p);
    41     for(int i=1;i<=n;i++)
    42     {
    43         for(int j=1;j<=m;j++)
    44         {
    45             ll xxx;
    46             scanf("%ll",&xxx);
    47             x[i]+=xxx;
    48             y[j]+=xxx;
    49         }
    50     }
    51     anwser();
    52     
    53     printf("%d",ans);
    54     
    55     return 0;
    56 }

    思路:首先我们可以得知如果你选择了i行,则你一定选择了k-i列,我们对每一行每一列都处理出一个前缀和,然后只要是这i行和这(k-i)列,答案一定最优,和选取顺序无关

    那么,再开两个数组,用堆维护一下就可以了

  • 相关阅读:
    poj1191(記憶化搜索)
    poj1088(記憶化搜索)
    二叉樹鏈表
    19_高级映射:一对多查询(使用resultMap)
    18_高级映射:一对一查询(使用resultMap)
    17_高级映射:一对一查询(使用resultType)
    15_CXF和Spring开发手机号查询网站
    14_CXF发布REST服务
    13_CXF和Spring整合发布服务
    12_CXF入门
  • 原文地址:https://www.cnblogs.com/suishiguang/p/6038713.html
Copyright © 2020-2023  润新知