题目:给你一个n行m列的矩阵,再给你k次操作机会,每次都可以令答案加上一行或一列,并且选中的那一行或一列会被消除,问你答案最大是多少
思路:
枚举加贪心
可以先枚举所有行被选中的情况,每个行有没有选中的情况都枚举一遍
然后再根据选中的行再去贪心的选择最大的几列
而这里的枚举是利用01枚举进行操作,每行有被选中就做个标记,之后贪心选列的时候就把之前选的的那些数字去掉
(其实借鉴了很多雨巨的思路,一开始看到这题真的无从下手,尤其01枚举这里,感觉到不好实现,在此谢谢雨巨啦)
AC代码

#include <iostream>
#include <string.h>
#include <algorithm>
typedef long long ll;
using namespace std;
int a[16][16]= {0};
int b[16];
long long row[16]= {0};
long long  line[16]= {0};
int main()
{
    int n,m,k;
    cin>>n>>m>>k;
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<m; j++)
        {
            cin>>a[i][j];
            row[i]+=a[i][j];
        }
    }
    long long ans=0;//答案
    if(k>n)k=n;
    if(k>m)k=m;
    int state=(1<<n)-1;//每个状态,最多有2的n次方减一的状态
    for(int i=0; i<=state; i++) //枚举所有行的情况
    {
        int cnt=0,j=0;//cnt代表所有选取的行数,j代表当前行数
        long long num=0;
        memset(b,0,sizeof(b));//每次循环要记得清空
        memset(line,0,sizeof(line));
        int x=i;
        while(x) //位运算
        {
            if(x&1)
            {
                cnt++;
                b[j]=1;//如果x的该位数是1说明目前的行数被选中了
            }
            j++;
            x>>=1;
        }
        int cntl=k-cnt;//选择的列数有多少
        if(cntl<0)continue;//如果<0说明选取的行数多了
        for(int f=0; f<n; f++) //被选中的行数记得加起来
            if(b[f])num+=row[f];
        for(int f=0; f<n; f++)
        {
            for(int t=0; t<m; t++)
            {
                if(!b[f])line[t]+=a[f][t];//去掉之前选中的行里的数字
            }
        }
        sort(line,line+m);
        for(int i=1,j=m-1;i<=cntl;i++,j--) //最大的几列加起来
            num+=line[j];
        ans=max(ans,num);
    }
    cout<<ans<<endl;
    return 0;
}