zoukankan      html  css  js  c++  java
  • 选数字

    题目描述 LYK 找到了一个 n*m 的矩阵,这个矩阵上都填有一些数字,对于第 i 行第 j 列的位置上 的数为 ai,j。

    由于它 AK 了 noip2016 的初赛,最近显得非常无聊,便想到了一个方法自娱自乐一番。 它想到的游戏是这样的

    :每次选择一行或者一列,它得到的快乐值将会是这一行或者一列的 数字之和。之后它将该行或者该列上的数字都减去 p(之后可能变成负数)。

    如此,重复 k 次,它得到的快乐值之和将会是它 NOIP2016 复赛比赛时的 RP 值。 LYK 当然想让它的 RP 值尽可能高,于是它来求助于你。

    数据范围 总共 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。

    思路:

      开始没有想到正解,打了60分,还不错。

      正解就是把从一维单独取K次,

      然后枚举行和列个选了多少次(因为tx+ty=k ,所以,枚举它们的复杂度只有k)

      最后,因为我们是单独选的,没有考虑 行对列的影响,也没考虑列对行的影响,所以你要考虑它们互相影响。

      想一下:你每选一行,对于ty列中每一列都会减P,所有再减tx*ty个p就行。

      60分  

    #include<iostream>
    #include<queue>
    #include<vector>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int n,m,k,p;
    int a[1200][1200];
    priority_queue<long long>q;
    int main()
    {
        freopen("select.in","r",stdin);
        freopen("select.out","w",stdout);
        scanf("%d%d%d%d",&n,&m,&k,&p);
        for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            scanf("%d",&a[i][j]);
        if(k==1)
        {
            int maxn=-999999,w,tot=0;
            for(int i=1;i<=n;i++)
            {
                tot=0;
                for(int j=1;j<=m;j++)
                tot+=a[i][j];
                
                if(tot>maxn)    w=i,maxn=tot;
            }
            int maxnn=-99999,ww;
            for(int j=1;j<=m;j++)
            {
                tot=0;
                for(int i=1;i<=n;i++)
                    tot+=a[i][j];
                if(tot>maxnn)    maxnn=tot,ww=j;
            }        
            cout<<max(maxn,maxnn);
            return  0;
        }
        if(p==0)
        {
            long long  maxn=-9999999,w,tot=0;
            for(int i=1;i<=n;i++)
            {
                tot=0;
                for(int j=1;j<=m;j++)
                tot+=a[i][j];
                
                if(tot>maxn)    w=i,maxn=tot;
            }
            long long  maxnn=-999999,ww;
            for(int j=1;j<=m;j++)
            {
                tot=0;
                for(int i=1;i<=n;i++)
                    tot+=a[i][j];
                if(tot>maxnn)    maxnn=tot,ww=j;
            }
            cout<<(max(maxn,maxnn)*k);
            return 0;
        }
        if(n==1)
        {
            if(k<=1000)
            {
                long long tot=0,sum;
                for(int j=1;j<=m;j++)
                    tot+=a[1][j],q.push(a[1][j]-p);
                long long  x,ans=tot,kk=k-2;
                k--;
                while(k--)
                {
                    x=q.top();q.pop();
                    ans+=x;x-=p;
                    q.push(x);
                }
                sum=ans;
                while(!q.empty())    q.pop();
                
                ans=tot*2;
                for(int j=1;j<=m;j++)
                    q.push(a[1][j]-2*p);
                while(kk--)
                {
                    x=q.top();q.pop();
                    ans+=x;x-=p;
                    q.push(x);
                }
                cout<<max(ans,sum);
                return 0;
            }
            for(int j=1;j<=m;j++)
                q.push(a[1][j]);
            long long  x,ans=0; 
            while(k--)
            {
                x=q.top();q.pop();
                ans+=x;x-=p;
                q.push(x);
            }
            cout<<ans;
            return 0;
        }
        if(n*m<=30)
        {
            long long  maxn=-99999,w,tot=0;long long  maxnn=0,ww,ans=0;
            while(k--)
            {
            maxn=-99999,maxnn=-999999;
            for(int i=1;i<=n;i++)
            {
                tot=0;
                for(int j=1;j<=m;j++)
                tot+=a[i][j];
                
                if(tot>maxn)    w=i,maxn=tot;
            }
            
            for(int j=1;j<=m;j++)
            {
                tot=0;
                for(int i=1;i<=n;i++)
                    tot+=a[i][j];
                if(tot>maxnn)    maxnn=tot,ww=j;
            }
            ans+=max(maxn,maxnn);
            if(maxn>maxnn)
            {
                for(int j=1;j<=m;j++)
                a[w][j]-=p;
            }else
            {
                for(int i=1;i<=n;i++)
                    a[i][ww]-=p;
            }
            }
            
            cout<<ans;
        }
        return 0;
    }
    60分
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int N=1000005;
    long long ans,s1[N],s2[N],p1[N],p2[N];
    int k,n,m,i,j,p,A;
    int main()
    {
        freopen("select.in","r",stdin);
        freopen("select.out","w",stdout);
        scanf("%d%d%d%d",&n,&m,&k,&p);
        for (i=1; i<=n; i++)
        for (j=1; j<=m; j++)
        {
            scanf("%d",&A);
            s1[i]+=A;s2[j]+=A;
        }
        make_heap(s1+1,s1+1+n);
        make_heap(s2+1,s2+1+m);
        
        for( i=1;i<=k;i++)
        {
            p1[i]=p1[i-1]+s1[1];
            pop_heap(s1+1,s1+1+n);
            s1[n]-=m*p;
            push_heap(s1+1,s1+1+n);
            
            p2[i]=p2[i-1]+s2[1];
            pop_heap(s2+1,s2+1+m);
            s2[m]-=n*p;
            push_heap(s2+1,s2+1+n);
            
        }
        ans=-1LL*100000000*100000000;
        for(int i=0;i<=k;i++)
        ans=max(ans,p1[i]+p2[k-i]-1LL*i*(k-i)*p);
        cout<<ans;
        return 0;
    }
    满分代码
  • 相关阅读:
    用Canvas绘制一个钟表
    用css3做一个3D立方体
    函数调用的不同方式,以及this的指向
    Javascript 严格模式use strict详解
    前端开发页面的性能优化方案总结
    Promise对象解读
    Vue爬坑之vuex初识
    WEB前端性能优化小结
    navicat 注册码
    docker
  • 原文地址:https://www.cnblogs.com/CLGYPYJ/p/7634423.html
Copyright © 2011-2022 走看看