剪了我N久的枝...终于涉险飘过了...2958ms.....

     DP....因为马的范围只能影响到两行之内...所以我每两行两行处理...先把两行内放马的情况打出来....那么.两行放马10个以下互不冲突..有近5000种放法..直接dp..至少5000*5000*10=2.5*10^8..而且判断当前状态能否放在已有皇后的情况下..状态更新时,前后的马是否会互相攻击等相当耗时...

     所以...然后就是各种剪枝了.....

     开始以为这种方法就是状态压缩DP...刚才发现我这压根就没压缩状态..赤裸裸的DP了....状态压缩DP效率高很多...


Program:

#include<iostream>
#include<cmath>
#include<stack>
#include<queue>
#include<set>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#define ll long long
#define oo 1000000007
using namespace std;
struct node1
{
int h[9][2],num;
}a[5005],p;
int b[70][2505],bnum[70];
int n,m,dp[2][5005][11];
char arc[10][10];
void build_B() // 当前在两行内放马的方案能和哪些放皇后的方案共存
{
int i,j,x1,x2;
for (i=0;i<=63;i++) // 两行内放皇后,不考虑冲突,一共64种情况
{
x1=i/8+1; x2=i%8+1;
for (j=1;j<=p.num;j++)
{
if (p.h[j][0]==1 && x1==p.h[j][1]) goto A;
if (p.h[j][0]==2 && x2==p.h[j][1]) goto A;
}
b[i][++bnum[i]]=m; // ok,挂到后面去....
A: ;
}
return;
}
void dfs(int y,int x) // 搜索出两行内放10个以下马互不冲突的所有情况
{
int i,j;
if (p.num==10) return;
for (i=1;i<=p.num;i++)
{
if (abs(p.h[i][0]-y)==1 && abs(p.h[i][1]-x)==2) return;
if (abs(p.h[i][0]-y)==2 && abs(p.h[i][1]-x)==1) return;
}
p.num++;
p.h[p.num][0]=y; p.h[p.num][1]=x;
a[++m]=p;
build_B();
for (j=x+1;j<=8;j++) dfs(y,j);
for (i=y+1;i<=2;i++)
for (j=1;j<=8;j++)
dfs(i,j);
p.num--;
return;
}
void prework()
{
int i,j,p1,p2,k;
memset(bnum,0,sizeof(bnum));
m=0;
p.num=0;
a[++m]=p;
build_B();
for (i=1;i<=2;i++)
for (j=1;j<=8;j++)
dfs(i,j);
return;
}
bool f(int i,int j) // 判断方案j在上,方案i在下..能否不冲突
{
int p1,p2;
for (p1=1;p1<=a[i].num;p1++)
for (p2=1;p2<=a[j].num;p2++)
{
if (abs(a[i].h[p1][0]-a[j].h[p2][0]-2)==2 && abs(a[i].h[p1][1]-a[j].h[p2][1])==1) return false;
if (abs(a[i].h[p1][0]-a[j].h[p2][0]-2)==1 && abs(a[i].h[p1][1]-a[j].h[p2][1])==2) return false;
}
return true;
}
int getnow(int t) // 将这两行皇后的情况转化成相应的代号
{
int x1,x2;
for (x1=1;x1<=8;x1++)
if (arc[t][x1]=='*') break;
for (x2=1;x2<=8;x2++)
if (arc[t+1][x2]=='*') break;
x1--; x2--;
return x1*8+x2;
}
int main()
{
int T,ii,jj,i,j,x,t,k,now,pre,ans,num1,num2;
prework();
scanf("%d",&T);
while (T--)
{
scanf("%d",&n);
for (i=0;i<=8;i++) gets(arc[i]+1);
memset(dp,0,sizeof(dp));
k=0;
now=getnow(1);
num1=bnum[now];
for (ii=1;ii<=num1;ii++)
{
i=b[now][ii];
dp[k][i][a[i].num]=1;
}
pre=now;
for (t=3;t<=8;t+=2)
{
k=1-k;
memset(dp[k],0,sizeof(dp[k]));
now=getnow(t);
num1=bnum[now];
num2=bnum[pre];
for (ii=1;ii<=num1;ii++)
{
i=b[now][ii];
for (jj=1;jj<=num2;jj++)
{
j=b[pre][jj];
if (a[i].num+a[j].num>n || !f(j,i)) continue; // 耗时!!
for (x=n-a[i].num;x>=a[j].num;x--)
dp[k][i][a[i].num+x]+=dp[1-k][j][x];
}
}
pre=now;
}
ans=0;
for (i=1;i<=m;i++) ans+=dp[k][i][n];
printf("%d\n",ans);
}
return 0;
}