开始呢,做的时候是选取最小的列和最小的行,然后谁小就替换谁,wa了,想了下,如果每替换一行或一列,就去修改所有受影响的行和列,是不是有点太麻烦了。就网上搜了下:http://blog.youkuaiyun.com/f_zyj/article/details/52216205
行最多只有10行,所有的状态一共最多也就1024种,可以把行的这些状态全都枚举出来,选出符合条件的,再去贪心的选取替换哪些列。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXR = 12;
const int MAXC = 210;
LL G[MAXR][MAXC];
LL RM[MAXR];
LL CM[MAXC];
vector<LL> h;
LL Sum = 0;
LL calc(LL num)
{
LL res = 0;
while(num)
{
if(num&1) ++res;
num >>= 1;
}
return res;
}
bool cmp(const LL& a, const LL& b)
{
return a > b;
}
int main()
{
LL n,m,x,k;
cin >> n >> m >> x >> k;
h.resize(m,0);
for(LL i = 0; i < n; ++i)
{
for(LL j = 0; j < m; ++j)
{
cin >> G[i][j];
RM[i] += G[i][j];
CM[j] += G[i][j];
Sum += G[i][j];
}
}
LL rowMax = x*m;
LL colMax = x*n;
LL Ceil = 1LL<<n;
LL ans = Sum;
for(LL i = 0; i < Ceil; ++i)
{
LL ret = Sum;
LL cnt = calc(i);
if(cnt > k) continue;
vector<int> record;
for(int r = 0; r < n; ++r)//计算出替换行后的收益
{
if((i>>r)&1)
{
ret += rowMax - RM[r];
record.push_back(r);
}
}
for(int j = 0; j < m; ++j)//计算替换每一列所得的收益
{
h[j] = colMax - CM[j];
for(int k = 0; k < record.size(); ++k)
h[j] += G[record[k]][j]-x;
}
sort(h.begin(),h.end(),cmp);//将收益降序排序,选取大的收益
for(int j = 0; j+cnt < k && h[j] > 0; ++j)//负的收益不要
ret += h[j];
ans = max(ret,ans);
}
cout << ans << endl;
return 0;
}