目录
描述
有一个正方形的墙,由N*N个正方形的砖组成,其中一些砖是白色的,另外一些砖是黄色的。Bob是个画家,想把全部的砖都涂成黄色。但他的画笔不好使。当他用画笔涂画第(i, j)个位置的砖时, 位置(i-1, j)、 (i+1, j)、 (i, j-1)、 (i, j+1)上的砖都会改变颜色。请你帮助Bob计算出最少需要涂画多少块砖,才能使所有砖的颜色都变成黄色。
输入
本题有多组测试数据(25组以内),每一组中第一行是一个整数n (1≤ n ≤15),表示墙的大小。接下来的n行表示墙的初始状态。每一行包含n个字符。第i行的第j个字符表示位于位置(i,j)上的砖的颜色。“w”表示白砖,“y”表示黄砖。
输出
输出为一行,如果Bob能够将所有的砖都涂成黄色,则输出最少需要涂画的砖数,否则输出“inf”。
样例输入
5
wwwww
wwwww
wwwww
wwwww
wwwww
样例输出
15
思路
使用暴力算法,局部枚举第一行以确定所有上色可能。
核心:为使上一行颜色恒为黄色,下一行上色情况一定。以此类推,只要对第一行所有情况进行枚举,即可确定整面墙体上色情况。
1.封装函数judge():用于判断该第一行情况下是否能完成整墙上色。
- 算法思路:先置第一行上色情况。
- 根据上一行上色情况判断本行是否上色。依次计算每行上色。
- 判断该上色思路能否达成整墙上色。
2.封装函数enumerate():
- 枚举思路:每格砖只有上色与否两种可能,用二进制表示。
3.考虑到连续测试,每次开始务必初始化上色统计。
代码示范
#define _CRT_SECURE_NO_WARNINGS //所有头文件和宏定义为个人爱好
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <cstring>
#include <string.h>
#include <math.h>
#include <cmath>
#include <iostream>
#include <vector>
#include <map>
#include <queue>
#define maxf 16
using namespace std;
int judge(int(*ori)[maxf], int(*paint)[maxf], int n)
{
for (int i = 0; i < n-1; i++)
{
for (int j = 0; j < n; j++)
{
paint[i + 1][j] = ori[i][j] + paint[i][j]; //根据上一行情况统计本行上色情况
if (i - 1 > -1)paint[i + 1][j] += paint[i - 1][j];
if (j - 1 > -1)paint[i + 1][j] += paint[i][j - 1];
if (j + 1 < n)paint[i + 1][j] += paint[i][j + 1];
paint[i + 1][j] %= 2;
}
}
for (int j = 0; j < n; j++)
{
int flag=paint[n - 2][j] + paint[n - 1][j]; //判断在上一行限制下,最后一行能否转为黄色
if (j + 1 < n)flag += paint[n - 1][j+1];
if (j - 1 > -1)flag += paint[n - 1][j - 1];
flag %= 2;
if (flag != ori[n - 1][j])return maxf * maxf; //原色为白,不上色;原色为黄,被迫上色均为上色失败
}
int step = 0;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)step += paint[i][j]; //统计上色次数
}
return step;
}
int enumerate(int (*ori)[maxf], int(*paint)[maxf], int n)
{
int minc = maxf * maxf;
int step = 0;
while (!paint[0][n]) //二进制溢出,枚举完成
{
step = judge(ori, paint, n);
if (step < minc)minc = step;
paint[0][0]++; //设置第一行情况
int cnt = 0; //进行二进制算法,从低位开始检查
while (paint[0][cnt] > 1) //逢二进一
{
paint[0][cnt] = 0;
paint[0][++cnt]++;
}
}
return minc;
}
int main()
{
int n;
while (cin >> n)
{
int ori[maxf][maxf];
int paint[maxf][maxf];
for (int i = 0; i < n; i++)
{
char c=getchar(); //输入墙面原始色彩
for (int j = 0; j < n; j++)
{
c = getchar();
if (c == 'w')ori[i][j] = 1; //需要上色
else ori[i][j] = 0;
paint[i][j] = 0; //初始化上色情况
}
}
getchar();
paint[0][n] = 0; //初始化枚举情况
int step = enumerate(ori, paint, n);
if (step == maxf * maxf)cout << "inf" << endl;
else cout << step << endl;
}
return 0;
}