这题是真的超出自己能力范围了,写完数据读入后,想了一会竟无从下手,不知道该怎么写。
看题解的过程中也很迷,觉得很麻烦,贪心的思想却又加上了枚举(这点可以从题目给的数据范围看出,居然只是一个15*15的矩阵)。
思路:
- 先读入数据,然后将每一行的总和记录下来;
- 利用二进制位运算,用二进制串来表示这一行是否被选中,从0到2^n-1进行枚举,将所有行可能被选中的情况全部枚举一遍;
- 对于每次枚举,将相应列的和算出来,因为选中行后,该行内的元素会变成0,所以算列和的时候就不能算进去;
- 将列和排序,从大到小选择剩下可以选择的列,加到总和上;
- 每次枚举都记录当前的总和和ans进行比较,ans取最大的那个,这样所有的情况都枚举完之后,ans就是最大的那个。
需要注意的点有: - 如果可以取得次数k已经大于n或者m了,那么就不用比较了,直接全取就行,这是一个比较特殊的地方;
- 还有就是n和m ,谁大谁小是不确定的,这就可能会导致suml小于0.
using namespace std;
#include<bits/stdc++.h>
int mp[20][20],row[20],col[20],sr[20],sl[20];
int deal(int n){
memset(sr,0,sizeof(sr));
int cnt=0;
int i=0;
while(n)
{
sr[i]=n&1;
if(sr[i] == 1) cnt++;
n=n>>1;
i++;
}
return cnt;
}
int main(){
int n,m,k;
cin>>n>>m>>k;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>mp[i][j];
row[i]+=mp[i][j];
}
}
long long ans=0;
if(k>n) k=n;
if(k>m) k=m;
int tmp=(1<<n)-1;
int sumh=0,suml=0;
for(int t=0;t<=tmp;t++)
{
long long sum=0;
sumh=deal(t);
suml=k-sumh;
if(suml<0) continue;
for(int i=0;i<n;i++)
{
if(sr[i]) sum+=row[i];
}
memset(sl,0,sizeof(sl));
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(!sr[i]) sl[j]+=mp[i][j];
}
}
sort(sl,sl+m);
for(int j=m-1;j>=m-suml;j--) sum+=sl[j];
ans=max(ans,sum);
}
cout<<ans;
return 0;
}