aoj0525
一、题意:题目大致是讲一个烧饼铺烤烧饼,在一个n X m (1<=n<=10,1<=m<=10000)的烤桌上面摆着一堆烧饼,数字1表示烧饼正面,0表示烧饼反面。然后你每次可以将一整行或者一整列的烧饼翻面,即正面翻成反面或者反面翻成正面。但是必须是一整列或者一整行的翻,问最多可以使都少烧饼翻成正面?题意还是很好懂的。
二、思路:由于n比较小,所以可以对行DFS,那列呢?其实列很好处理,对每一列统计1的个数或者0的个数,保留最大者即是最大的正面个数,试想如果当前列正面个数多,那这一列就不翻面就好了,如果反面多,那么将该列翻面即可使得原先反面变成正面。所以对列直接统计即可。这题需要注意的是无论哪一行或者那一列先翻面都是无谓的,不影响结果,即翻面的顺序不影响结果,只考虑该行或该列是否要翻面即可,所以可以直接DFS。输入数据的第一行表示n和m,接下来的n X m的0和1的矩阵就表示当前烧饼状态,输入0 0结束。总而言之,此题很暴力。
三、代码:
#include"iostream" #include"stdio.h" #include"algorithm" #include"vector" #include"queue" using namespace std; int r,c; int maze[15][10005]; int maxRes; void Rev(int n) { for(int j=0;j<c;j++) maze[n][j]=maze[n][j]^1; } int Cal() { int sum=0; for(int j=0;j<c;j++) { int cnt=0; for(int i=0;i<r;i++) { cnt+=maze[i][j]; } sum+=max(cnt,r-cnt); } return sum; } void Dfs(int n) { if(n==r) { maxRes=max(maxRes,Cal()); return; } Rev(n); Dfs(n+1); Rev(n); Dfs(n+1); } int main() { // freopen("in.txt","r",stdin); while(scanf("%d%d",&r,&c)==2,r&&c) { maxRes=0; for(int i=0;i<r;i++) { for(int j=0;j<c;j++) scanf("%d",&maze[i][j]); } Dfs(0); cout<<maxRes<<endl; } return 0; }