zoukankan      html  css  js  c++  java
  • 选数字(贪心)

    选数字

    题目描述:
    LYK 找到了一个 n*m 的矩阵,这个矩阵上都填有一些数字,对于第 i 行第 j 列的位置上的数为 ai,j。
    由于它 AK 了 noip2016 的初赛,最近显得非常无聊,便想到了一个方法自娱自乐一番。
    它想到的游戏是这样的:每次选择一行或者一列,它得到的快乐值将会是这一行或者一列的数字之和。之后它将该行或者该列上的数字都减去 p(之后可能变成负数)。如此,重复 k次,它得到的快乐值之和将会是它 NOIP2016 复赛比赛时的 RP 值。
    LYK 当然想让它的 RP 值尽可能高,于是它来求助于你。
    输入格式:
    第一行 4 个数 n,m,k,p.
    接下来 n 行 m 列,表示 ai,j。
    输出格式:
    输出一行表示最大 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。
    思路:
    观察可以发现如果确定选几次行几次列
    那么选的顺序是无所谓的
    对于选行 那么肯定是选最优的 对于行也是
    所以
    先处理出选0~k次行和列的最优值
    然后枚举选i次行则选k-i次列
    行的最优值加上列的最优值减去选行和列交叉的地方多选的即可
    ans=max(ans,s[i]+r[i]-(i)*(k-i)*p)

    #include<iostream>
    #include<cstdio>
    #include<queue>
    #define lon long long
    using namespace std;
    const int maxn=1010;
    const lon inf=-1000000000000000;
    lon n,m,k,p,h[maxn*maxn],l[maxn*maxn],a[maxn][maxn];
    priority_queue<lon>q;
    lon init()
    {
        lon x=0,f=1;char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    int main()
    {
        freopen("select.in","r",stdin);
        freopen("select.out","w",stdout);
        n=init(),m=init(),k=init(),p=init();
        for(lon i=1;i<=n;i++)
          for(lon j=1;j<=m;j++)
          a[i][j]=init();
        for(lon i=1;i<=n;i++)
        {
            lon sum=0;
            for(lon j=1;j<=m;j++)
            sum+=a[i][j];
            q.push(sum);
        }
        for(lon i=1;i<=k;i++)
        {
            lon sum=q.top();
            q.pop();
            h[i]=h[i-1]+sum;
            q.push(sum-p*m);
        }
        while(!q.empty()) q.pop();
        for(lon j=1;j<=m;j++)
        {
            lon sum=0;
            for(lon i=1;i<=n;i++)
            sum+=a[i][j];
            q.push(sum);
        }
        for(lon i=1;i<=k;i++)
        {
            lon sum=q.top();
            q.pop();
            l[i]=l[i-1]+sum;
            q.push(sum-p*n);
        }
        lon ans=inf;
        for(lon i=0;i<=k;i++)
        ans=max(ans,h[i]+l[k-i]-i*(k-i)*p);
        cout<<ans;
        fclose(stdin);fclose(stdout);
        return 0;
    }
  • 相关阅读:
    将iso镜像转换为docker镜像
    Linux awk使用方法~~整理
    Linux sed使用方法
    Linux 环境变量梳理
    学习docker——命令总结
    Golang 字符串操作--使用strings、strconv包
    WebSocket实现一个聊天室
    学习WebSocket
    PHP面试题整理
    php使用gd库输出中文内容的图片
  • 原文地址:https://www.cnblogs.com/cax1165/p/6070900.html
Copyright © 2011-2022 走看看