/*
构图:对于任意一行,如果该行里的格子彼此可到达(没有障碍物),则把他们归为同一个
点,纵向也是如此。 构造出来的横向点和纵向点,如果彼此覆盖,则连一条边,最后直接
求最大匹配。
15MS 312K
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define SIZE 88
using namespace std;
int N,ans;
char map[8][8];
bool cnt[SIZE][SIZE],vis[SIZE];
int link[SIZE];
int col[8][8],row[8][8];
int cc,rr;
bool dfs(int lt)
{
for(int r=1; r<=cc; r++)
{
if(cnt[lt][r] && !vis[r])
{
vis[r] = true;
if(link[r] == -1 || dfs(link[r]))
{
link[r] = lt;
return true;
}
}
}
return false;
}
int main()
{
while(~scanf("%d",&N) && N)
{
for(int i=1; i<=N; i++)
{
for(int j=1; j<=N; j++)
{
cin >> map[i][j];
col[i][j] = row[i][j] = 0;
}
}
cc = rr = ans = 0;
memset(cnt,0,sizeof(cnt));
memset(link,-1,sizeof(link));
for(int i=1; i<=N; i++)
{
for(int j=1; j<=N; j++)
{
if(map[i][j] == 'X')
continue;
if(col[i][j] == 0)
{
col[i][j] = ++cc;
int t = i + 1;
while(t <= N)
{
if(map[t][j] == 'X')
break;
col[t][j] = cc;
t ++;
}
}
if(row[i][j] == 0)
{
row[i][j] = ++rr;
int t = j + 1;
while(t <= N)
{
if(map[i][t] == 'X')
break;
row[i][t] = rr;
t ++;
}
}
}
}
for(int i=1; i<=N; i++)
{
for(int j=1; j<=N; j++)
{
cnt[row[i][j]][col[i][j]] = true;
}
}
for(int i=1; i<=rr; i++)
{
memset(vis,0,sizeof(vis));
if(dfs(i))
ans ++;
}
printf("%d\n",ans);
}
return 0;
}