NC200190 矩阵消除游戏

题目

题目描述

牛妹在玩一个名为矩阵消除的游戏,矩阵的大小是 nm 列,第 i 行第 j 列的单元格的权值为 ai,j ,牛妹可以进行 k 个回合的游戏,在每个回合,牛妹可以选择一行或者选择一列,然后将这一行或者这一列的所有单元格中的权值变为 0 ,同时牛妹的分数会加上这一行或者这一列中的所有单元格的权值的和。

牛妹想最大化她的得分,球球你帮帮她吧!

输入描述

第一行三个整数 n,m,k
接下来 n 行每行 m 个整数表示矩阵中各个单元格的权值。

输出描述

输出一个整数表示牛妹能获得的最大分数。

示例1

输入

3 3 2
101 1 102
1 202 1
100 8 100

输出

414

备注

1n,m15

1ai,j1e61knm

题解

知识点:枚举,贪心,位运算。

首先发现直接贪心是不可行的,每次清零会导致行列信息的都发生变化。考虑枚举行或列,这里选择枚举行的选择情况。

一共 2n 种情况,用一个整型变量保存选择的状态即可。

在行选择完之后,对列贪心地从大开始选,注意选择的列数量只能是 min(kcnt(i),m)cnt(i) 表示选择的行数量,由于剩余数量可能超过列数 m ,因此用 min 限制。

在累加过程可以用前缀和预处理,可以节省一点时间。

时间复杂度 O(2nmlogm)

空间复杂度 O(nm)

代码

#include <bits/stdc++.h>
using namespace std;
int a[20][20], r[20], c[20], ccur[20];
int cnt(int n) {
int ans = 0;
while (n) {
ans++;
n &= n - 1;
}
return ans;
}
int main() {
std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, m, k;
cin >> n >> m >> k;
for (int i = 0;i < n;i++)
for (int j = 0;j < m;j++)
cin >> a[i][j];
for (int i = 0;i < n;i++)
for (int j = 0;j < m;j++)
r[i] += a[i][j];
for (int i = 0;i < m;i++)
for (int j = 0;j < n;j++)
c[i] += a[j][i];
int ans = 0;
for (int i = 0;i < (1 << n);i++) {
if (cnt(i) > k) continue;
memcpy(ccur, c, sizeof(c));
int sum = 0;
for (int j = 0;j < n;j++) {
if ((i >> j) & 1) {
sum += r[j];
for (int u = 0;u < m;u++) ccur[u] -= a[j][u];
}
}
sort(ccur, ccur + m, [&](int a, int b) {return a > b;});
for (int j = 0;j < min(k - cnt(i), m);j++) sum += ccur[j];
ans = max(ans, sum);
}
cout << ans << '\n';
return 0;
}
posted @   空白菌  阅读(61)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示