题目:给你一个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; }