#include <iostream>
using namespace std;
int maxn, plan; //最大城堡数,和当前计划的城堡数
char a[4][4]; //储存城堡,城堡为‘y’
int n;
void DFS(int m);
bool canplace(int m);
int main()
{
while ((cin >> n) && n)
{
maxn = plan = 0; //由于有多组输入,maxn,plan是全局变量,所以需要每组开始输入时初始化。
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> a[i][j]; //输入
}
}
DFS(0);
cout << maxn << endl;
}
}
bool canplace(int m)
{
int x = m / n, y = m % n;
if (a[x][y] == 'X')
return false;
else
{
for (int i = x; i >= 0; i--)
{
if (a[i][y] == 'y')
return false;
if (a[i][y] == 'X')
break;
}
for (int i = y; i >= 0; i--)
{
if (a[x][i] == 'y')
return false;
if (a[x][i] == 'X')
break;
}
return true;
}
}
void DFS(int m)
{
if (m == n * n)
{
maxn = max(maxn, plan);
// return;
} //到最终位置n*n时,找到最大城堡数,然后返回
else
{
if (canplace(m))
{ //如果可以存放
plan++;
a[m / n][m % n] = 'y'; //开始存放
DFS(m + 1);
plan--;
a[m / n][m % n] = '.'; //由于a[4][4]是全局变量数组,在更改完后必须在回溯是改回原样
}
DFS(m + 1); //关键步骤,两个作用:如果m位不能放城堡,那就看下一位,
//如果可以放,但是可能不是最优解,所以在每一步的回溯过程中去找m位不放城堡的其他解,以寻求最大解
}
}