#include<cstdio>
#include<cmath>
#include<string>
#include<algorithm>
#include<iostream>
using namespace std;
int mp[10][10];
int vx[10], vy[10], vd1[20], vd2[20];//分别表示行与列与左对角线和右对角线
int n,ans;
void dfs(int x,int p)//一个用来表示行x ,一个用来表式放的是黑皇后(1)还是白皇后(2) ,先放黑后放白
{
if (x == n&&p==2)//到了最后一行且放的是白皇后则结束
{
ans++;
return;
}
if (x == n)
{
dfs(0, p + 1);//黑皇后放完开始放白皇后,又重新从第0行开始放白皇后
return;
}
for (int i = 1; i <= n; i++)//x代表行i代表列
{//列如 mp[x][y]==0则表示不可以放置皇后 ,mp[x][y]==1则表示可以放置皇后 ,
if (mp[x][i] && vy[i] != 3 && vy[i] != p && vd1[x + i] != 3 && vd1[x + i] != p && vd2[x - i + n] != 3 && vd2[x - i + n] != p)
//x+i左下对角,x-i+n右下对角
// 注意是对每一行的每一个值减或加比如
// 1 2 3 4
// 1 (1+1) (1+2) (1+3) (1+4)
// 2 2+1 2+2 2+3(5) 2+4(6)
// 3 3+1 3+2(5) 3+3(6) 3+4
// 4
// 1 2 3 4
// 1 1-1+4 1-2+4 1-3+4 1-4+4
// 2 2-1+4(5) 2-2+4(4) 2-3+4 2-4+4
// 3 3-1+4(6) 3-2+4(5) 3-3+4(4)
// 4
//表示mp[x][i]第x行第i列的位置,存在也就是说可以放皇后,vy[i]!=3(主要针对两次都放置了之后而言)表示列的方向没有放置两个皇后因为1代表黑皇后2代表白皇后 1+2=3表示两个皇后均已经放置,!=p是针对第一次而言第一次p=1 ,第二次p=2 而已经填入的列如vy[i]=1,所以不冲突
{
mp[x][i] = 0;//表示改位置放入皇后;
vy[i] += p;
vd1[x + i] += p;
vd2[x - i + n] += p;
dfs(x + 1, p);
vy[i] -= p;
vd1[x + i] -= p;
vd2[x - i + n] -= p;
mp[x][i] = 1;//重新清回来表示该位置可以防止皇后为了其他的情况可以正常运行
}
}
}
int main()
{
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
scanf("%d", &mp[i][j]);
//数为1可以放置皇后数为0不可以放置皇后
}
}
dfs(0, 1);
cout << ans << endl;
return 0;
}
/*#include<bits/stdc++.h>
using namespace std;
const int s = 100;
int vy[s], vd[s], vv[s];//列左下,右下对角线
int map[s][s];
int n, ans;
void dfs(int x, int p)
{
if (x == n && p == 2)
{
ans++;
return;
}
if (x == n && p == 1)//表示第一种皇后放完的情况 p不加也可以我们直接在最后面判断即可
{
dfs(0, p + 1);
return;//这里必须有return 因为他不用计算之后回溯继续往下计算,因为一种皇后已经被算完了
}
for (int i = 1; i < n; i++)
//这里横向来看一共就是实打实的n个格子不可能从零开始因为这样凑不齐对角线,必须到n不然的话第n-1个格子凑不齐
{
//x可以表示行map==1表示可以放置 ,,3表示两次都放过了
if (map[x][i] && vy[i] != 3 && vy[i] != p && vd[x + i] != p % %vd[x + i] != 3 && vv[x - i + n] != 3 && vv[x - i + n] != p)
{
map[x][i] = 0;//标记为已访问,之后不可以访问
vy[i] += p;
vd[x + i] += p;
vv[x - i + n] += p;
dfs(x + 1, p);//表示访问下一个
vy[i] -= p;
vd[x + i] -= p;
vv[x - i + n] -= p;//回溯
map[i][j] = 1;
}
}
}
int main()
{
cin >> n;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
cin >> map[i][j];
}
}
dfs(0, 1);//从零开始比较好因为这样前面那个就表示已经放好,而1表示等待放入,1表示放入白皇后,2表示放入黑皇后,当一个格子等于三就表示他黑皇后放过,白皇后也放过
//因为一个格子既可以放黑也可以放白,是一种相对概念当一个格子放了黑那么其他就只能放白,但是第二位同时这个格子也可以放置白,那么相对黑也会产生不同的情况
cout << ans;
return 0;
}*/