思路:将行和列分开考虑。用优先队列,计算出行操作i次的幸福值r[i],再计算出列操作i次的幸福值c[i]。然后将行取i次操作和列取k-i次操作,那么多加的幸福值就是i*(k-i)*p,因为无论先操作行还是列,每操作一次一个格子只减一次p。这样记录下最大的幸福值。
代码:
#include<bits/stdc++.h> using namespace std; #define ll long long const int N=1e6+5; const int M=1e3+5; const ll INF=1e18; priority_queue<ll>row,col; ll r[N],c[N]; int a[M][M]; int main() { ios::sync_with_stdio(false); cin.tie(0); int n,m,k,p; cin>>n>>m>>k>>p; for(int i=0;i<n;i++) { ll sum=0; for(int j=0;j<m;j++) { cin>>a[i][j]; sum+=a[i][j]; } row.push(sum); } for(int j=0;j<m;j++) { ll sum=0; for(int i=0;i<n;i++) sum+=a[i][j]; col.push(sum); } for(int i=1;i<=k;i++) { ll temp=row.top(); row.pop(); r[i]=r[i-1]+temp; row.push(temp-m*p); } for(int i=1;i<=k;i++) { ll temp=col.top(); col.pop(); c[i]=c[i-1]+temp; col.push(temp-n*p); } ll ans=-INF; for(int i=0;i<=k;i++) { ans=max(ans,r[i]+c[k-i]-1ll*i*(k-i)*p); } cout<<ans<<endl; return 0; }