http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=0525
题意:药药!切克闹! 煎饼果子来一套!有一个烤饼器可以烤r行c列的煎饼,煎饼可以正面朝上(用1表示)也可以背面朝上(用0表示)。一次可将同一行或同一列的煎饼全部翻转。现在需要把尽可能多的煎饼翻成正面朝上,问最多能使多少煎饼正面朝上?
输入:多组输入,每组第一行为二整数r, c (1 ≤ r ≤ 10, 1 ≤ c ≤ 10 000),剩下r行c列表示煎饼初始状态。r=c=0表示输入结束。
输出:对于每组输入,输出最多能使多少煎饼正面朝上
注意数据范围!!从这里联想到解题方法,顺带查阅bitset的相关资料!(笔者前几篇博客有)
最近做的题感觉bfs什么时候都能够插一脚哈!!
.
.
.
.
.
.
.
.
.
.
分析:这个是二维的穷举,因为列数比较多行数比较少,所以可对行做深度优先遍历穷举所有行的情况。这里用bitset保存每一行的情况,对于行的翻装,只需要用自带的flip函数。对于每一行都确定动作时,统计每一列翻时会出现的正面朝上的值以及不翻时的值,取较大数。此时为行动作确定时,列动作可以做到的最优值。因此穷举所有行情况即可求出实际最优值。
#include <cstdio>
#include <algorithm>
#include <bitset>
using namespace std;
const int MAX_R = 10;
const int MAX_C = 10000;
//input
int R, C;
bitset<MAX_C> a[MAX_R];
int ans;
void dfs(int k){
if(k == R){
//row certain
int result = 0; //cur max value
for(int j = 0; j < C; j ++){
int upNum = 0; //up numbers without fliping
for(int i = 0; i < R; i ++){
if(a[i][j]) upNum ++;
}
result += max(upNum, R - upNum);
}
ans = max(ans, result);
return;
}
//without fliping
dfs(k + 1);
//·flip
a[k].flip();
dfs(k + 1);
}
void solve(){
ans = 0;
dfs(0);
printf("%d\n", ans);
}
int main(int argc, char const *argv[]){
while(scanf("%d %d", &R, &C)){
if(R == 0 && C == 0) break;
for(int i = 0; i < R; i ++){
for(int j = 0; j < C; j ++){
bool tmp;
scanf("%d", &tmp);
a[i][j] = tmp;
}
}
solve();
}
return 0;
}