有一个烤饼器可以烤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; }