AOJ 0525 Osenbei
题意
IOI制果公司用创业以来的传统制法煎制煎饼。这种传统制法是用炭火在一定时间内烤正面,正面烤后翻转,用炭火在一定时间内烤背面。保持着这个传统,用机器煎煎饼。该机器将煎饼排成纵R(1≤R≤10)行、横C(1≤C≤10000)列的长方形来烤。通常是自动驾驶,正面烤好后一齐把煎饼翻过来背面烤。有一天,煎煎饼的时候,在翻煎饼之前发生了地震,几张煎饼都翻了。幸运的是,炭火的状态还保持在适当的状态,但如果再烧到正面,就会超过创业以来的传统规定的烧时间,煎饼的正面会被烧得太久,无法作为商品上市。于是,他赶紧把机器改为手动操作,只把还没有翻过来的煎饼翻过来。这台机器,可以同时翻过来几行横的,同时翻过来几列竖的,可惜的是,煎饼一张一张地翻不过来。取的,需要时间和地震中没有里返ら煎饼的间前面太烧作为商品无法发货,所以旁边的几行,同时一次翻过来,继续,纵向的几排翻过来,同时一次间前面不太烤两面可以烤煎饼,也就是说,“可以出货煎饼”决定尽可能多的数量。也考虑横的行一行也不翻转,或者纵的列一列也不翻转的情况。请写下输出能出货的煎饼张数最大值的程序。地震之后,煎饼就变成了下面这个样子。黑色圆圈表示正面烧制的状态,白色圆圈表示背面烧制的状态。(用的翻译软件,大概意思理解就好)
注意,R的上限10小于C的上限10000。
输入由多个数据集组成。每个数据集以以下形式给出:在输入的第一行中,以空白为间隔写有两个整数R、C(1≤R≤10,1≤C≤10 000)。接着的R行表示地震后的煎饼状态。第(i+1)行(1≤i≤R)有C个整数ai,1, ai,2,……, ai,C以空白为间隔写,ai,j表示i行j列的煎饼状态。ai,j为1表示正面烧制,0表示背面烧制。当C和R均为0时,指示输入结束,数据集的数目不超过5。
每个输出数据集输出1行可发货的煎饼的最大张数。
题解
思路:因为行数最多只有10行,所以先确定行再判断列,行的话最多是210种可能,然后每种可能再去判断列,使得列中的1数量最多。具体细节看代码注释。
#include<iostream>
using namespace std;
int r, c;
int arr[15][10005];
int ans;
void dfs(int t) {//t是行号
if(t == r) { //最后一行
int sum = 0; //记录整个行列中1的数量
for(int i = 0; i < c; i++) {
int tsum = 0;//记录当前列中1的数量
for(int j = 0; j < r; j++)
tsum += arr[j][i]; //因为是1,0两种状态,所以直接相加即可
sum += max(tsum, r - tsum);//如果1多就直接加,不然就反转
}
ans = max(ans, sum);//ans是最终值,如果sum比ans大就替代
return;
}
dfs(t + 1);//第t行不反转,进入下一行
for(int i = 0; i < c; i++)//反转当前行
arr[t][i] = !arr[t][i];
dfs(t + 1);//反转后进入的下一行
}
int main() {
while(cin >> r >> c, r + c) {
for(int i = 0; i < r; i++)
for(int j = 0; j < c; j++)
cin >> arr[i][j];
ans = 0;
dfs(0);
cout << ans << endl;
}
return 0;
}