题意:
牛妹在玩一个名为矩阵消除的游戏,矩阵的大小是n行m列,第i行第j列的单元格的权值为
a
i
,
j
,
a_{i,j},
ai,j,,牛妹可以进行k个回合的游戏,在每个回合,牛妹可以选择一行或者选择一列,然后将这一行或者这一列的所有单元格中的权值变为0,同时牛妹的分数会加上这一行或者这一列中的所有单元格的权值的和。
牛妹想最大化她的得分,球球你帮帮她吧!
题解:
如果这个题想直接暴力对所有行和列进行dfs的话,这样应该是会超时的,试了好几种方法,都T了,很遗憾。
这题无论是dfs或者是二进制枚举,核心都是,枚举行或者枚举列,再去贪心,也就是说,如果你枚举的是行,那么你就去贪心列,如果你枚举的是列,那你就去贪心行。
假设我们枚举的是列,那么我们求所枚举的列时,顺带将去除所枚举的列后,每行的值都存在一个数组里,然后对数组进行排序。如果挑选次数还有剩余,有限挑选大的。
代码:
/*Keep on going Never give up*/
#pragma GCC optimize(3,"Ofast","inline")
#include<iostream>
#include<cstdio>
#include <string.h>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<vector>
#include<cmath>
#include <math.h>
#include<algorithm>
#define int long long
using namespace std;
const int maxn = 110;
const int MaxN = 0x3f3f3f3f;
const int MinN = 0xc0c0c00c;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll mod=1e9+7;
ll a[maxn][maxn];
ll rem[maxn];
signed main()
{
int n,m,k;
cin>>n>>m>>k;
ll ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
cin>>a[i][j];
ans+=a[i][j];
}
}
if(k>=min(n,m)){
cout<<ans<<endl;
return 0;
}
ans=0;
for(int t=0;t<(1<<m);t++){
int cnt=__builtin_popcountll(t);
if(cnt>k) continue;
int temp=0;
for(int i=1;i<=n;i++){
for(int j=0;j<m;j++){
if(1<<j & t) temp+=a[i][j+1];
else rem[i]+=a[i][j+1];
}
}
sort(rem+1,rem+n+1,greater<int>());
for(int i=1;i<=k-cnt;i++){
temp+=rem[i];
}
ans=max(ans,temp);
memset(rem,0,sizeof rem);
}
cout<<ans<<endl;
return 0;
}