AOJ 0525 Osenbei

有一个烤饼器可以烤r行c列的煎饼,煎饼可以正面朝上(用1表示)也可以背面朝上(用0表示)。一次可将同一行或同一列的煎饼全部翻转。现在需要把尽可能多的煎饼翻成正面朝上,问最多能使多少煎饼正面朝上? 
         输入:多组输入,每组第一行为二整数r, c (1 ≤ r ≤ 10, 1 ≤ c ≤ 10 000),剩下r行c列表示煎饼初始状态。r=c=0表示输入结束。 
         输出:对于每组输入,输出最多能使多少煎饼正面朝上。

测试数据:

输入:2 5
     0 1 0 1 0
     1 0 0 0 1 
输出:9
输入:
3 6
1 0 0 0 1 0
1 1 1 0 1 0
1 0 1 1 0 1
输出:15
思路:先对行进行翻转,若有r行,一共要2^r次,对于行翻转后的每一种情况,在进行列的翻转,列不需要真的翻转,只需要统计一下每一列是正面朝上的煎饼多还是反面朝上的煎饼多,取总和。
对于这2^r个总和,取最大的那个即可。
代码:
#include<iostream>
#include<bitset>
#include<algorithm>
using namespace std;
bitset<10000>cookie[10];
int main() {
    int r, c;
    while (cin >> r >> c&&r) {
        int result = 0;
        for (int i = 0;i < r;i++)
            for (int j = 0;j < c;j++) {
                bool what;
                cin >> what;
                cookie[i][j] = what;
            }
        int permute = 1 << r;int k;
        for ( k = 0;k < permute;k++) {//行的变换总共有2^r个,k取遍各种情况
            for (int j = 0;j < r;j++) {//每一种情况对应着这r行的一次变化(每一行翻转或者不翻转)
                if (k & (1 << j))//对于每一个k,(1<<j)与i的二进制对应位上若都为1,这一行翻转(1<<j取值为1,10,100,1000,....)
                    cookie[j].flip();          //举个例子,若k=11,对应着(1<<j)为1和10时都进行翻转,也就是此次循环只有第一第二行进行翻转,其余行不变
            }
            //对于每次行翻转后的情况,考虑每一列的翻转使得朝上煎饼数最多
            int possible_num=0;
            for (int j = 0;j < c;j++) {
                int up_number=0;
                for (int i = 0;i < r;i++) {
                    if (cookie[i][j])
                        up_number++;
                }
                possible_num += max(up_number,r-up_number);
            }
            result =max(result,possible_num);
            for (int j = 0;j < r;j++) {
            if (k & (1 << j))
                cookie[j].flip();
        }
        }
        cout << result << endl;
    }
    
    return 0;
}
原文地址:https://www.cnblogs.com/ZefengYao/p/5826242.html