#include<stdio.h>
#include<string.h>
#include<math.h>
#include<stdlib.h>
int map[16][16], temp[16][16], row[16];
int n, min, cnt;
void meiju(int x)//枚举所有绘画情况
{
memset(row, 0, sizeof(row));
int i = 0;
while(x)
{
row[i++] = x&1;
x >>= 1;
}
}
void paint(int x,int y)//画一格
{
temp[x][y] = !temp[x][y];
if(x-1 >= 0)
temp[x-1][y] = !temp[x-1][y];
if(y-1 >= 0)
temp[x][y-1] = !temp[x][y-1];
if(x+1 < n)
temp[x+1][y] = !temp[x+1][y];
if(y+1 < n)
temp[x][y+1] = !temp[x][y+1];
cnt++;
}
void check()//根据第一行进行暴力检查
{
//如果上一行的当前列不是黄色则对当前行当前列进行绘画
for(int i = 1; i < n; ++i)
{
for(int j = 0; j < n; ++j)
{
if(temp[i-1][j] != 1)
paint(i,j);
}
}
//检查经过绘画后的最后一行是否全为黄色
for(int i = 0; i < n; ++i)
{
if(temp[n-1][i] != 1)
return; //不全为黄色说明此种绘画方法失败
}
if(min > cnt) //成功则保存最小的次数
min = cnt;
}
int main()
{
int i, j, k, t;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
min = n*n + 1; //求出画的最小次数
char s[16];
for(i = 0; i < n; ++i)//输入字符
{
scanf("%s", s);
for(j = 0; j < n; ++j)
{
if(s[j] == 'w') //白色标记为0
map[i][j] = 0;
else
map[i][j] = 1;
}
}
k = pow(2.0,n); //枚举第一行所有画的情况
for(i = 0; i < k; ++i)
{
meiju(i);
cnt = 0; //初始化
memcpy(temp, map, sizeof(map));
for(j = 0; j < n; ++j) //画出第一行
{
if(row[j] == 1)
paint(0,j);
}
check();
}
if(min == n*n+1)
printf("inf\n");
else
printf("%d\n", min);
}
return 0;
}
题意:给出一个画板,画板上有n*n个格子,初始状态上随机格数黄色和白色,可以对其中一个格子进行变色,每进行一次变色该格子的上下左右四个格子都需要变色,问需要多少次变色可使所有格子变成黄色,若有多种可能取次数最小的,若无可能则输出inf。
思路:对第一行所有可能的变色情况进行枚举,然后根据第一行的颜色逐行推出下一行的变色情况,最后判断最后一行的颜色是否全为黄色,如果是则说明可行,保存最小的次数。