//题目大意:给一个最大不超过4x4的图,用X表示墙壁,问能在这张图上放多少个碉堡,每个碉堡可以向上,下,左,右四个方向发射子弹,但是墙可以挡住子弹,我们希望在放置最多碉堡的情况下,保证两两碉堡不会相互攻击到对方
//最优策略:尽量在墙的四周放置碉堡。
//先将每个墙的位置记录下来,在墙的四周(上下左右放碉堡是最好的),按墙四周的所能安放碉堡的数目排序
//比如 . .X2 X1这个墙四周可以放4个碉堡,排在前面,下一个X2周围只能放两个排在后面
// .X1.
// . . .
//遍历每一个墙,在墙的周围放上碉堡,当然了,放置的时候还要判断该位置能否放碉堡。
//最优策略:尽量在墙的四周放置碉堡。
//先将每个墙的位置记录下来,在墙的四周(上下左右放碉堡是最好的),按墙四周的所能安放碉堡的数目排序
//比如 . .X2 X1这个墙四周可以放4个碉堡,排在前面,下一个X2周围只能放两个排在后面
// .X1.
// . . .
//遍历每一个墙,在墙的周围放上碉堡,当然了,放置的时候还要判断该位置能否放碉堡。
//遍历完后,还要重新遍历整个图,防止没有墙壁以及 墙壁数量较少导致遗漏的情况。
//因为墙壁隔着两者不会相互攻击,所以不是二分图的情况
#include<iostream>
#include<cstdio>
#include<memory>
#include<algorithm>
using namespace std;
struct Z
{
int x;
int y;
int kong;
}z[17];//黑块
int map[5][5];
int n;//4
int cmp(Z a,Z b)
{
return a.kong>b.kong;
}
int testR(int r,int c)//判断r行是否允许安放碉堡
{
int flagL=1;//左边允许标志
int flagR=1;//右边允许标志
if(c==1){//如果在第一列,向右扫描
for(;c<=n;c++)
{
if(map[r][c]=='.')continue;
if(map[r][c]=='X')break;
if(map[r][c]=='N'){
flagR=0;
break;
}//break;
}
}else if(c==n){//如果在最后一列,向左扫描
for(;c>=1;c--)
{
if(map[r][c]=='.')continue;
if(map[r][c]=='X')break;
if(map[r][c]=='N'){
flagL=0;
break;
}//break;
}
}else{//如果在中间
int zuo=c-1;
int you=c+1;
for(;you<=n;you++)
{
if(map[r][you]=='.')continue;
if(map[r][you]=='X')break;
if(map[r][you]=='N'){
flagR=0;
break;
}//break;
}
for(;zuo>=1;zuo--)
{
if(map[r][zuo]=='.')continue;
if(map[r][zuo]=='X')break;
if(map[r][zuo]=='N'){
flagL=0;
break;
}//break;
}
}
return flagL && flagR;
}
int testC(int r,int c) //判断列c是否允许安放碉堡
{
int flagup=1;
int flagdown=1;
if(r==1){//扫描下方
for(;r<=n;r++)
{
if(map[r][c]=='.')continue;
if(map[r][c]=='X')break;
if(map[r][c]=='N'){
flagdown=0;
break;
}//break;
}
}else if(r==n){//扫描上方
for(;r>=1;r--)
{
if(map[r][c]=='.')continue;
if(map[r][c]=='X')break;
if(map[r][c]=='N'){
flagup=0;
break;
}//break;
}
}else{
int shang=r-1;
int xia=r+1;
for(;xia<=n;xia++)
{
if(map[xia][c]=='.')continue;
if(map[xia][c]=='X')break;
if(map[xia][c]=='N'){
flagdown=0;
break;
}//break;
}
for(;shang>=1;shang--)
{
if(map[shang][c]=='.')continue;
if(map[shang][c]=='X')break;
if(map[shang][c]=='N'){
flagup=0;
break;
}//break;
}
}
return flagup && flagdown;
}
int main()
{
scanf("%d",&n);
while(n)
{
int i,j;
int pos=0;
for(i=1;i<=n;i++)
{
getchar();
for(j=1;j<=n;j++)
{
scanf("%c",&map[i][j]);
if(map[i][j]=='X')
{
z[pos].x=i;
z[pos].y=j;
pos++;
}
}
}
int k=0;
for(i=1;i<=n;i++) //统计每个墙周围能安放碉堡的个数
{
for(j=1;j<=n;j++)
{
if(map[i][j]=='X')
{
int cnt=0;
if(i>=2 && map[i-1][j]=='.'){
cnt++;
}
if(i<=n-1 && map[i+1][j]=='.'){
cnt++;
}
if(j<=n-1 && map[i][j+1]=='.'){
cnt++;
}
if(j>=2 && map[i][j-1]=='.'){
cnt++;
}
z[k].kong=cnt;
k++;
}
}
}
sort(z,z+pos,cmp); //排序
int ans=0;
for(i=0;i<pos;i++)//遍历每一个墙
{
int x=z[i].x;
int y=z[i].y;
//上和下,列不变
int shang=x-1;
if(shang>=1 && map[shang][y]=='.')//如果这个位置没有东西
{
if(testR(shang,y))//如果这个行可以放
{
if(testC(shang,y))
{
map[shang][y]='N';
ans++;
}
}
}
int xia=x+1;
if(xia<=n &&map[xia][y]=='.')
{
if(testR(xia,y))//如果这个行可以放
{
if(testC(xia,y))
{
map[xia][y]='N';
ans++;
}
}
}
//左和右行不变
int zuo=y-1;
int you=y+1;
if(zuo>=1 && map[x][zuo]=='.')
{
if(testR(x,zuo))//如果这个行可以放
{
if(testC(x,zuo))
{
map[x][zuo]='N';
ans++;
}
}
}
if(you<=n && map[x][you]=='.')
{
if(testR(x,you))//如果这个行可以放
{
if(testC(x,you))
{
map[x][you]='N';
ans++;
}
}
}
}
for(i=1;i<=n;i++) //补漏
{
for(j=1;j<=n;j++)
{
if(map[i][j]=='.')
{
if(testR(i,j)&&testC(i,j))
{
map[i][j]='N';
ans++;
}
}
}
}
// for(i=1;i<=n;i++)
// {
// for(j=1;j<=n;j++)
// {
// printf("%c ",map[i][j]);
// }
// printf("\n");
// }
printf("%d\n",ans);
scanf("%d",&n);
}
return 0;
}