题目![在这里插入图片描述](https://img-blog.csdnimg.cn/20210328172638976.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0Nhc3NpZV96a3E=,size_16,color_FFFFFF,t_70)
思路
之前做过的题,又不会做了😭。
基本思路就是枚举+dfs。枚举选择x(
x
∈
[
0
,
k
]
x\in[0,k]
x∈[0,k])行,那么还需要选择k-x列。
通过dfs来计算n行里面选择哪x行,通过二进制(1个int型整数)来标记选了哪些行,进行必要的剪枝。确定了要选的x行后,剩下则需要计算删除该x行后,每一列的和,取和最大的k-x列,统计答案,并更新答案。
注意,判断int型每一位上是0还是1时,最好用>>而不是用<<,否则会超时。 玄学问题,和底层的硬件实现和cache命中有关,等俺以后研究研究是咋回事o(╥﹏╥)o。超时代码在这里
代码
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <vector>
#include <map>
#include <queue>
#include <limits.h>
#include <stack>
using namespace std;
typedef long long ll;
const int maxn = 20;
int n, m, k, sum = 0, ans = 0;
int a[maxn][maxn], lie[maxn];
int getCnt(int bit)
{
int res = 0;
while(bit)
{
res += bit&1;
bit >>= 1;
}
return res;
}
void solve(int id, int bit, int x) //正在处理第id行,bit标记哪些行已经选了, 共选x行
{
int cnt = getCnt(bit); //已选cnt行
int bb = bit;
if(n-id+1<x-cnt) return ; //剩余的待考虑的行数不够了
if(cnt==x)
{
int cur = 0;
for(int i = 1; i <= n; i++, bb >>= 1)
if(bb&1)
for(int j = 1; j <= m; j++)
cur += a[i][j];
for(int j = 1; j <= m; j++)
{
lie[j] = 0;
bb = bit;
for(int i = 1; i <= n; i++, bb >>= 1)
if(!(bb&1)) lie[j] += a[i][j];
}
sort(lie+1, lie+1+m, greater<int>());
for(int i = 1; i <= k-x; i++) cur += lie[i];
ans = max(ans, cur);
return ;
}
solve(id+1, bit, x); //不选第id行
solve(id+1, bit|(1<<(id-1)), x);
}
int main()
{
//freopen("/Users/zhangkanqi/Desktop/11.txt", "r", stdin);
scanf("%d %d %d", &n, &m, &k);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
{
scanf("%d", &a[i][j]);
sum += a[i][j];
}
if(k>=n || k>=m) ans = sum;
else
{
for(int x = 0; x <= k; x++) //选x行,k-x列
solve(1, 0, x);
}
printf("%d\n", ans);
return 0;
}