题意:有一个烤饼器可以烤r行c列的煎饼,煎饼可以正面朝上(用1表示)也可以背面朝上(用0表示)。一次可将同一行或同一列的煎饼全部翻转。现在需要把尽可能多的煎饼翻成正面朝上,问最多能使多少煎饼正面朝上?
输入:多组输入,每组第一行为二整数r, c (1 ≤ r ≤ 10, 1 ≤ c ≤ 10 000),剩下r行c列表示煎饼初始状态。r=c=0表示输入结束。
输出:对于每组输入,输出最多能使多少煎饼正面朝上。
(翻译参考自:http://bbs.byr.cn/#!article/ACM_ICPC/73337?au=Milrivel)
分析:这个是二维的穷举,因为列数比较多行数比较少,所以可对行做深度优先遍历穷举所有行的情况。这里用bitset保存每一行的情况,对于行的翻装,只需要用自带的flip函数。对于每一行都确定动作时,统计每一列翻时会出现的正面朝上的值以及不翻时的值,取较大数。此时为行动作确定时,列动作可以做到的最优值。因此穷举所有行情况即可求出实际最优值。
1 #include <cstdio> 2 #include <algorithm> 3 #include <bitset> 4 5 using namespace std; 6 7 const int MAX_R = 10; 8 const int MAX_C = 10000; 9 10 //input 11 int R, C; 12 bitset<MAX_C> a[MAX_R]; 13 14 int ans; 15 16 void dfs(int k){ 17 if(k == R){ 18 //row certain 19 int result = 0; //cur max value 20 for(int j = 0; j < C; j ++){ 21 int upNum = 0; //up numbers without fliping 22 for(int i = 0; i < R; i ++){ 23 if(a[i][j]) upNum ++; 24 } 25 result += max(upNum, R - upNum); 26 } 27 ans = max(ans, result); 28 return; 29 } 30 //without fliping 31 dfs(k + 1); 32 //·flip 33 a[k].flip(); 34 dfs(k + 1); 35 36 a[k].flip(); 37 } 38 39 void solve(){ 40 ans = 0; 41 dfs(0); 42 printf("%d ", ans); 43 } 44 45 int main(int argc, char const *argv[]){ 46 47 while(scanf("%d %d", &R, &C)){ 48 if(R == 0 && C == 0) break; 49 50 for(int i = 0; i < R; i ++){ 51 for(int j = 0; j < C; j ++){ 52 bool tmp; 53 scanf("%d", &tmp); 54 a[i][j] = tmp; 55 } 56 } 57 solve(); 58 } 59 60 return 0; 61 }