问题描述:
有一个正方形的墙,由N*N个正方形的砖组成,其中一些砖是白色的,另外一些砖是黄色的。Bob是个画家,想把全部的砖都涂成黄色。但他的画笔不好使。当他用画笔涂画第(i, j)个位置的砖时, 位置(i-1, j)、 (i+1, j)、 (i, j-1)、 (i, j+1)上的砖都会改变颜色。请你帮助Bob计算出最少需要涂画多少块砖,才能使所有砖的颜色都变成黄色。
输入
第一行是个整数t(1≤t ≤20),表示要测试的案例数。然后是t个案例。每个案例的首行是一个整数n (1≤n ≤15),表示墙的大小。接下来的n行表示墙的初始状态。每一行包含n个字符。第i行的第j个字符表示位于位置(i,j)上的砖的颜色。“w”表示白砖,“y”表示黄砖。
输出
每个案例输出一行。如果Bob能够将所有的砖都涂成黄色,则输出最少需要涂画的砖数,否则输出“inf”。
算法分析:
和熄灯问题很相似,略有改动
#include <iostream>
using namespace std;
int wall[16][17]={0},press[16][17]={0};
//黄色为0,白色表示1
/*
推测验证过程:
根据第一行猜测
*/
int guess(const int& wallsize) {
//根据press第1行和wall数组,计算press其他行的值
for (int r=1; r<wallsize; r++) {
for (int c=1; c<=wallsize; c++) {
press[r+1][c]=(wall[r][c]+press[r][c]+press[r-1][c]+press[r][c-1]+press[r][c+1])%2;
}
}
//判断所计算的press数组能否将最后一行全变为黄色0
for(int c=1; c<=wallsize; c++) {
if ((press[wallsize][c-1]+press[wallsize][c]+press[wallsize][c+1]+press[wallsize-1][c])%2 != wall[wallsize][c]) {
return 1001;
}
}
//算出需要的步数
int steps=0;
for (int r=1; r<=wallsize; r++) {
for (int c=1; c<=wallsize; c++) {
if (press[r][c]==1) {
steps++;
}
}
}
return steps;
}
/*
枚举过程:
对press第1行的元素press[1][1]~press[1][6]的各种取值进行枚举
*/
int enumerate(const int& wallsize) {
int minsteps=1001;
int steps=0;
int c;
while (press[1][wallsize+1]<1){
steps = guess(wallsize);
if (steps<minsteps){
minsteps = steps;
}
press[1][1]++;
c=1;
while(press[1][c]>1) {
press[1][c]=0;
c++;
press[1][c]++;
}
}
return minsteps;
}
int main() {
int cases=0;
cin >> cases;
char color;
int wall_size=0;
int minsteps=0;
for(int k=0; k<cases; k++) {
//初始化
for (int r=0; r<16; r++){
for (int c=0; c<17; c++){
wall[r][c]=0;
press[r][c]=0;
}
}
//输入数据
cin >> wall_size;
for(int i=1; i<wall_size+1; i++) {
for (int j=1; j<wall_size+1; j++){
cin >> color;
wall[i][j] = color=='y' ? 0:1;
}
}
//枚举
minsteps = enumerate(wall_size);
if (minsteps>1000){
cout << "inf" << endl;
}
else {
cout << minsteps << endl;
}
}
}