AOJ 0525 穷举

题意:有一个烤饼器可以烤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 }
原文地址:https://www.cnblogs.com/7hat/p/3605315.html