回溯会超时,要用把黑白棋盘分别dp,把对角线的格按大小排序后当做放车问题来计算,对角线摞起来不规则,就按照对角行格数从小到大画再dp,就不会有漏掉的情况
//回溯
#include<stdio.h>
#include<string.h>
int zhu[16],fu[16],n,k,tot;
int c[9][18];
void search(int hang,int j,int lie)
{
if(hang==n||j>n*n||lie==n)
return;
else
{
int z,f;
f=hang+lie;
z=hang-lie+n;
if(zhu[z]==1||fu[f]==1)
{
if(lie==n-1)
search(hang+1,j,0);
else
search(hang,j,lie+1);
}
else
{
zhu[z]=1;fu[f]=1;
c[n][j+1]++;
if(lie==n-1)
search(hang+1,j+1,0);
else
search(hang,j+1,lie+1);
zhu[z]=0;fu[f]=0;
if(lie==n-1)
search(hang+1,j,0);
else
search(hang,j,lie+1);
}
}
}
int main()
{
int i;
memset(c,0,sizeof(c));
for(i=1;i<=8;i++)
{
memset(zhu,0,sizeof(zhu));
memset(fu,0,sizeof(fu));
n=i;
search(0,0,0);
}
for(;;)
{
scanf("%d %d",&n,&k);
if(!n&&!k)
break;
printf("%d\n",c[n][k]);
}
return 0;
}
//dp
#include<stdio.h>
#include<string.h>
int dp[9][18],dp2[9][18],bai[9][18];
int pan[9]={20,1,1,3,3,5,5,7,7};
int pan2[9]={0,2,2,4,4,6,6,8,8};
int main()
{
int i,j,k,l,m,n;
memset(dp,0,sizeof(dp));
memset(dp2,0,sizeof(dp2));
memset(bai,0,sizeof(bai));
dp[1][0]=1;dp[1][1]=1;
for(i=2;i<=8;i++)
{
dp[i][0]=1;
for(j=1;j<=pan[i];j++)
{
dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*(pan[i]-j+1);
}
}
dp2[0][0]=1;dp2[1][1]=2;dp2[1][0]=1;dp2[1][1]=2;
for(i=2;i<=7;i++)
{
dp2[i][0]=1;
for(j=1;j<=pan2[i];j++)
{
dp2[i][j]=dp2[i-1][j]+dp2[i-1][j-1]*(pan2[i]-j+1);
}
}
memset(bai[0],0,sizeof(0));
bai[2][0]=1;
bai[2][1]=2;
// for(i=3;i<=8;i=i+2)
// memcpy(bai[i],dp2[i-1],sizeof(int)*18);
//memcpy(bai,dp2,sizeof(dp2));bai[1][0]=1;
for(;;)
{
scanf("%d %d",&n,&k);
if(!n&&!k)
break;
m=0;
if(k==1&&n==1)
{
printf("1\n");
continue;
}
dp2[1][0]=1;dp2[1][1]=2;
for(i=0;i<=k;i++)
{
//if(i>pan[i])
// break;
m+=dp[n][i]*dp2[n-1][k-i];
}
printf("%d\n",m);
}
return 0;
}