围棋由方形网格棋盘和黑白棋子构成。现在棋盘的某方形区域内摆满棋子,下图为该棋盘4*4的区域内摆放棋子的情况。如果用b和w表示该方形网格中棋子的颜色,b为黑色,w为白色。这样该图形可用下面来的矩阵来表示:
bwbw
wwww
bbwb
bwwb
现玩一个游戏,游戏规则是:如果将其中的某一个棋子由黑色变成白色(称为一次变换),则周围四个方向上的棋子将会改变颜色,也就是如果原来棋子的颜色是白色则变成黑色,是黑色则会变成白色。比如上面的棋盘中,将第三行第一个棋子由黑色变成白色,则对应的棋盘会变成下面的颜色:
bwbw
bwww
wwwb
wwwb
上述这样的变换称为一次变换。请编写程序,希望通过最少次数的变换将棋盘中的棋子全部变成白色或者黑色。
输入要求:输入第一行为整数n,表示棋盘中放摆放棋子的行数和列数,其后的n行,每行有n个字符,由b和w组成,分别表示棋子的初始颜色。
输出要求:输出1个整数,占1行,表示最少的变换次数。
样例输入:
bwwb
bbwb
bwwb
bwww
样例输出:4
代码如下
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int n;
string *s;
const int NotFound = -1;
const int INF =INT_MAX;
int nxt[][2] = {
{0,0},{0,1},{0,-1},{1,0},{-1,0}//五个翻转棋子状态
};
void filp(int num)//对n及其周围的棋子进行翻转
{
int x = num / n;
int y = num % n;
for (int i = 0; i < 5; i++)//对自身和周围四颗棋子进行翻转
{
int nx = x + nxt[i][0];
int ny = y + nxt[i][1];
if (nx < 0 || ny < 0 || nx >= n || ny >= n)
continue;
else
{
if (s[nx][ny] == 'w') s[nx][ny] = 'b';
else s[nx][ny] = 'w';
}
}
}
bool trick()
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
if (s[i][j] != s[0][0])
return false;
}
return true;
}
int dfs(int num, int ans)
{
if (trick())
return ans;
if (num > n*n)
return INF;
filp(num);//翻转
int ans1 = dfs(num + 1, ans + 1);
filp(num);//翻转回来置为初始状态
int ans2 = dfs(num + 1, ans);
return min(ans1, ans2);
}
int main()
{
cin >> n;
s = new string[n + 1];
for (int i = 0; i < n; i++)
cin >> s[i];
int res = dfs(0, 0);
if (res != INF)
cout << res;
else
cout << "Impossible";
return 0;
}