枚举:POJ画家问题
/***********
POJ 画家问题
测试:
input:
3
yyy
yyy
yyy
output:
0
input:
5
wwwww
wwwww
wwwww
wwwww
wwwww
output:
15
**********/
#include <iostream>
#include <cmath>
using namespace std;
int min_painting_blocks(int input_state[17][17], int n)
{
int min_bolcks = 300;
int painted_state[17][17] = {0}; // 存放对墙涂画的动作
// 枚举对第一行的墙的操作
int p = pow(2, n); // 计算第一行涂画的可能数
for(int d=0;d<p;d++){
int temp_bolcks = 0;
int flag = 1;// 标志:目前第一行的状态是否可以画满整个墙 0表示不好使
// 对目前第一行所引起的状态进行判断
for(int r=1;r<=n;r++){
for(int c=1;c<=n;c++){
painted_state[r+1][c] = (input_state[r][c] + painted_state[r][c] +
painted_state[r][c-1] + painted_state[r][c+1] + painted_state[r-1][c])%2;
}
}
for(int c=1;c<=n;c++){
if((painted_state[n][c]+painted_state[n][c-1]+painted_state[n][c+1]+painted_state[n-1][c])%2
!= input_state[n][c]){
flag = 0;
break;
}
}
if(flag==0){
// 更新下一个第一行状态
painted_state[1][1]++;
int t = 1;
while(painted_state[1][t]>1){
painted_state[1][t] = 0;
t++;
painted_state[1][t]++;
}
continue;
}
else{
// 如果可以画满,找到当前的涂画的砖块数
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
temp_bolcks += painted_state[j][k];
}
}
painted_state[1][1]++;
int t = 1;
while(painted_state[1][t]>1){
painted_state[1][t] = 0;
t++;
painted_state[1][t]++;
}
if(temp_bolcks<min_bolcks){
min_bolcks = temp_bolcks;
temp_bolcks = 0;
}
}
}
return min_bolcks;
}
int main()
{
int n=0; // 墙的大小
int min_blocks=300;
int input_state[17][17] = {0};
// 输入
cin >> n;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
char temp_c;
cin >> temp_c;
if(temp_c=='w'){
input_state[i][j] = 1;
}
else if(temp_c=='y'){
input_state[i][j] = 0;
}
}
}
// 对输入状态进行判断
min_blocks = min_painting_blocks(input_state, n);
if(min_blocks==300)
cout << "inf" << endl;
else
cout << min_blocks << endl;
return 0;
}