题意
国际象棋棋盘上象只能走对角线,如果两只象位于同一对角线上,它们将互相攻击。现在,给出n和k,在一个n*n的棋盘上放k个互不攻击的象有多少种方法?
另有题解
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#define mst(a,b) memset(a,b,sizeof(a))
typedef long long LL;
using namespace std;
const int N = 9;
int Cb[N],Cw[N],Rb[N][65],Rw[N][65];
//C[]-旋转45°后黑白棋每行格子数(白色多一行)、R[i][j]-前i行放j个棋子的方法数
void Init(int n){
mst(Cb,0);
mst(Cw,0);
Cw[1]=1;
for(int i=1;i<=n;i++){
if(i<=n/2){
Cw[i]=2*i-1;
Cb[i]=2*i;
}
else{
if(!Cw[n+1-i])
Cw[i]=Cw[i-1]+2;
else Cw[i]=Cw[n+1-i];
Cb[i]=Cb[n-i];
}
//cout<<"第"<<i<<"行白棋:"<<Cw[i]<<endl;
//cout<<"第"<<i<<"行黑棋:"<<Cb[i]<<endl;
}
}
void init(int n){
mst(Cb,0);
mst(Cw,0);
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if((i+j)&1) Cb[(i+j)>>1]++;
else Cw[(i+j)>>1]++;
}
}
/*for(int i=1;i<=n;i++){
cout<<"第"<<i<<"行白棋:"<<Cw[i]<<endl;
cout<<"第"<<i<<"行黑棋:"<<Cb[i]<<endl;
}*/
}
void Bishop(int n,int k,int C[],int R[][65]){
for(int i=0;i<=n;i++) R[i][0]=1;
for(int i=1;i<=k;i++) R[0][i]=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=C[i];j++)
R[i][j]=R[i-1][j]+R[i-1][j-1]*(C[i]-j+1);
}
int main()
{
int n,k;
while(scanf("%d%d",&n,&k)&&(n||k)){
Init(n); //两个init作用相同,初始化Cb、Cw数组
sort(Cb+1,Cb+n);
sort(Cw+1,Cw+n+1);
Bishop(n-1,k,Cb,Rb);
Bishop(n,k,Cw,Rw);
LL ans=0;
for(int i=0;i<=k;i++)
ans+=Rb[n-1][i]*Rw[n][k-i];
printf("%lld\n",ans);
}
return 0;
}