[NOIP 2023 模拟7]矩阵游戏

[NOIP 2023 模拟7]矩阵游戏

=> 题意:

这是一个n行m列的矩阵,将进行k次操作,每次操作将矩阵的某一行或某一列的所有元素的值减p,得分为修改前这一行或这一列的元素和。

求出k次操作能获得的分数的最大值。

=> 思路:

考虑贪心:我们每次选择 max(行max, 列max),并计入答案、减去相应的值

如果最优选择一直位于 行上 或 列上,则上述做法是正确的

但如果数据不保证上述条件......

举出反例:

2 5 5 5
5 5 5 5 5
1 1 1 1 1

所以换思路:

注意到:列上的操作对行上的操作是没有影响的,同样的,行上操作对列上操作没有影响

于是行和列分开贪心:前i次都用行删除的答案为f_i​,前i次都用列删除的答案为g_i​,则答案为 max(f_i+g_(k-i)−1LL*i∗(k−i)∗p)

=> 代码:

#include <bits/stdc++.h>
using namespace std;
#define LL long long
const int N=1e6+10;
LL n,m,k,p;
LL mapp[1001][1001];
LL hang[N],lie[N];

priority_queue<LL> q;

int main() {
	freopen("matrix.in","r",stdin);
	freopen("matrix.out","w",stdout);
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin>>n>>m>>k>>p;
	for(int i=1;i<=n;i++) {
		for(int j=1;j<=m;j++) {
			cin>>mapp[i][j];
		}
	}
	for(int i=1;i<=n;i++) {
		LL sum=0;
		for(int j=1;j<=m;j++) {
			sum+=mapp[i][j];
		}
		q.push(sum);
	}
	for(int i=1;i<=k;i++) {
		LL tmp=q.top();
		q.pop();
		hang[i]=hang[i-1]+tmp;
		q.push(tmp-m*p);
	}
	while(!q.empty()) q.pop();
	
	for(int i=1;i<=m;i++) {
		LL sum=0;
		for(int j=1;j<=n;j++) {
			sum+=mapp[j][i];
		}
		q.push(sum);
	}
	for(int i=1;i<=k;i++) {
		LL tmp=q.top();
		q.pop();
		lie[i]=lie[i-1]+tmp;
		q.push(tmp-n*p);
	}
	LL ans=-LLONG_MAX;
	for(int i=0;i<=k;i++) {
		ans=max(ans,hang[i]+lie[k-i]-1LL*i*(k-i)*p);
	}
	cout<<ans;
	return 0;
}
posted on 2024-11-04 20:28  Ueesugi_sakura  阅读(3)  评论(0编辑  收藏  举报