解题思路
地图很小,可以考虑二进制枚举。
首先读到地图数据之后,先把k处理一下,可以先求地图全部和,如果直接输出,我懒就没写。
后面用二进制枚举,去枚举到全部可能选的行。
如果枚举到这一行被选中,那么直接累加到答案。
如果枚举这一行未被选中,那么累加到列的和当中。
处理全部的行之后,对列和排序,从大到小累加进答案。再把这个答案和最终答案求最大值即可。
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 16;
int mapp[N][N], sum[N];
int main() {
ios::sync_with_stdio(false);
cout.tie(0); cin.tie(0);
int n, m, k;
cin >> n >> m >> k;
k=min(k,min(n,m));
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= m; ++j)
cin >> mapp[i][j];
int ans = 0;
for (int i = 0; i < 1 << m; ++i) {
int cnt = __builtin_popcount(i); //统计32位无符号整数的二进制1个数
if (cnt > k) continue;
memset(sum, 0, sizeof(sum));
int ret = 0;
for (int j = 1; j <= n; ++j) {
for (int y = 0; y < m; ++y)
if ((1 << y) & i)
ret += mapp[j][y + 1];
else
sum[j] += mapp[j][y + 1];
}
sort(sum + 1, sum + 1 + n, greater<int>());
for (int j = 1; j <= k - cnt; ++j)
ret += sum[j];
ans = max(ans, ret);
}
cout << ans << endl;
return 0;
} 后话
这里是我但是比赛时,还没想到二进制枚举的思路,直接暴力模拟,得分95分,4MS左右,实在不会证明它对,可是又答不上哪里不对。
可惜是ACM,错一个样例就是WA,OI的话95分也不错了呢。
这里看到了雨巨的题解!!太厉害啦,懂了。
当前不拿最大不代表我以后就拿不到了,当前一直拿最大会多拿很多不应该拿的
#include <bits/stdc++.h>
using namespace std;
int main (){
int n,m,k;
scanf("%d %d %d",&n,&m,&k);
int mapp[20][20];
int ans[20+20];
for(int i=0; i<n; ++i)
for(int j=0; j<m; ++j)
scanf("%d",&mapp[i][j]);
int num=0;
memset(ans,0,sizeof(ans));
for(int i=0; i<n; ++i)
for(int j=0; j<m; ++j) //把行和放进前n项
ans[i]+=mapp[i][j];
for(int i=0; i<m; ++i)
for(int j=0; j<n; ++j) //把列和放进后n项
ans[i+n]+=mapp[j][i];
while(k--){
int maxdata=ans[0],maxi=0;
for(int i=1; i<m+n; ++i) //找到行最大或列最大
if(ans[i]>ans[maxi]){
maxi=i;
maxdata=ans[i];
}
num+=maxdata;
ans[maxi]=0;
if(maxi<n)
for(int i=0; i<m; ++i) ans[i+n]-=mapp[maxi][i]; //这一行所在列全部减掉当前值
else
for(int i=0; i<n; ++i) ans[i]-=mapp[i][maxi-n]; //同理
}
printf("%d\n",num);
return 0;
}
//……哎,只能说当时太弱了吧,想当然了 
京公网安备 11010502036488号