这个题不能胡乱选择行或者列,因为你一旦选择了一列以后,接下来选一行一定会受到影响,不符合贪心的特点,就是子问题的求解不影响其他部分。所以可以枚举行,然后贪心列,这样列和列之间不会相互影响,可以贪心的来做,然后就是位运算枚举每一种行的选择情况。

这道题被坑了,主要还是基础知识不扎实,deal函数我直接把数组传进去,我以为里面变,不会影响外面的数组,然后就WA了两个小时,一直以为是什么逻辑上的问题,直到我突发奇想,想把数组输出出来看看,结果@_@ 很难过,所以数组一定要copy一份出来 (QaQ)

#include<bits/stdc++.h>
using namespace std;
int n,m,k;
const int M=20;
int a[M][M];
int hang[M];
int lie[M];
int sum;
bool cmp(int a,int b){
	return a>b;
}
long long deal( int c[], int b[],int num){
	int h[M];
	int l[M];
	memcpy(h,c,n*sizeof(int));
	memcpy(l,b,m*sizeof(int));
	int pos[M]={0};
	int cnt=0;
	long long sum=0;
	int tot=0;
	while(num){
		if((num&(-num))==1){
			pos[tot++]=cnt;
			sum+=h[cnt];
		}
		num>>=1;
		cnt++;
	}
	for(int i=0;i<m;i++){
		for(int j=0;j<tot;j++){
			l[i]-=a[pos[j]][i];
		}
	}
	sort(l,l+m,cmp);
	for(int i=0;i<k-tot;i++){
		sum+=l[i];
	}
	return sum;
}
int numb(int num){
    int cnt=0;
    while(num){
        if((num&(-num))==1){
            cnt++;
        }
        num>>=1;
    }
    return cnt;
}
int main(){
	cin>>n>>m>>k;
	for(int i=0;i<n;i++){
		for(int j=0;j<m;j++){
			cin>>a[i][j];
			hang[i]+=a[i][j];
            sum+=a[i][j];
		}
	}
    if(n<=k||m<=k){
       cout<<sum<<endl;
        return 0;
    }
	for(int j=0;j<m;j++){
		for(int i=0;i<n;i++){
			lie[j]+=a[i][j];
		}
	}
	long long ans=0;
	for(int i=0;i<=(1<<n)-2;i++){
        if(numb(i)>k)continue;
		ans=max(ans,deal(hang,lie,i));
	}
	cout<<ans<<endl;
	return 0;
}