我们第一次想到的贪心策略一定是找出和最大的行或者列来删除,每次都更新行和列
比如如图这种情况,这种情况就不如直接删除两行的多,所以本贪心策略有误
so我们可以枚举选的行的情况,然后再贪心的选择列和最大的列来做
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,k;
typedef long long ll;
const int N = 20;
int sum;
int col[N];
int a[N][N];
int calc(int x)
{
int ret = 0;
while(x)
{
ret++;
x -= x & -x;
}
return ret;
}
bool cmp(int x,int y)
{
return x>y;
}
int ret;
int main()
{
cin >> n >> m >> k;
for(int i = 0;i<n;i++)
{
for(int j = 0;j<m;j++)
{
cin >> a[i][j];
}
}
for(int st = 0;st<(1<<n);st++)
{
memset(col,0,sizeof(col));
sum = 0;
if(calc(st)>k) continue;
for(int i = 0;i<n;i++)
{
for(int j = 0;j<m;j++)
{
if((st>>i)&1) sum+=a[i][j];
else col[j]+=a[i][j];
}
}
sort(col,col+m,cmp);
int tmp = k-calc(st);
for(int i = 0;i<tmp;i++)
{
sum+=col[i];
}
ret = max(ret,sum);
}
cout << ret;
return 0;
}
这样写是有bug的,我们选列的时候有可能会越界
因为我们的k最高是n*m,假如不选行,全选列,列是不够选的啊,我们应该对col的遍历范围做点限制,不能超过m
正确代码√
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,k;
typedef long long ll;
const int N = 20;
int a[N][N];
int sum;
int col[N];
int calc(int x)
{
int ret = 0;
while(x)
{
ret++;
x -= x & -x;
}
return ret;
}
bool cmp(int x,int y)
{
return x>y;
}
int ret;
int main()
{
cin >> n >> m >> k;
for(int i = 0;i<n;i++)
{
for(int j = 0;j<m;j++)
{
cin >> a[i][j];
}
}
for(int st = 0;st<(1<<n);st++)
{
memset(col,0,sizeof(col));
sum = 0;
if(calc(st)>k) continue;
for(int i = 0;i<n;i++)
{
for(int j = 0;j<m;j++)
{
if((st>>i)&1) sum+=a[i][j];
else col[j]+=a[i][j];
}
}
sort(col,col+m,cmp);
int tmp = k-calc(st);
for(int i = 0;i<min(tmp,m);i++)
{
sum+=col[i];
}
ret = max(ret,sum);
}
cout << ret;
return 0;
}