题目链接
题意
一个大小是n行m列的矩阵,第i行第j列的单元格的权值为ai,j,每次可以选择一行或者选择一列,然后将这一行或者这一列的所有单元格中的权值变为0,分数会加上这一行或者这一列中的所有单元格的权值的和,进行k次,求最大的分数。
思路
- 利用状态压缩的方法选择一些行,其余的按降序选择列
- 注意如果k>min(n,m) 直接输出矩阵和即可,否则可能越界
参考代码
#include<bits/stdc++.h>
using namespace std;
int aa[20][20];
int len[510];
int cc[20][20];
int col[510];
int main()
{
long long n,m,k;
cin>>n>>m>>k;
long long sum=0,ans=0;
for(int i=0; i<n; i++)
{
int sum1=0;
for(int j=0; j<m; j++)
{
cin>>aa[i][j];
sum1+=aa[i][j];
sum+=aa[i][j];
}
len[i]=sum1;
}
if(k>=min(n,m))
{
cout<<sum<<endl;
return 0;
}
for(int i=0; i<=((1<<n)-1); i++)
{
int cs=0;
for(int j=0; j<=n-1; j++)
{
if((i&(1<<j))==(1<<j))
{
cs++;
}
}
if(cs>k)
continue;
memcpy(cc,aa,sizeof(aa));
long long sum2=0;
if(i!=0)
{
for(int j=0; j<=n-1; j++)
{
if((i&(1<<j))==(1<<j))
{
sum2+=len[j];
for(int k=0; k<m; k++)
{
cc[j][k]=0;
}
}
}
}
for(int j=0; j<m; j++)
{
int tmp=0;
for(int m=0; m<n; m++)
{
tmp+=cc[m][j];
}
col[j]=tmp;
}
sort(col,col+m);
for(int j=1; j<=k-cs; j++)
{
sum2+=col[m-j];
}
ans=max(ans,sum2);
}
cout<<ans<<endl;
}