题意:N*N的表格,给K只棋子放进去,要求同一斜线上至多有一只棋子,求方案数。
思路:首先将棋盘转45°,就变成横竖的问题了,显然奇数行和偶数行是无冲突的,考虑分开计算,到时候用乘法原理加起来即可,尽管每一行的格子数先增后减,将短的行先计算也无影响,又显然奇数行比偶数行多1行,最后要再计算一次。dp[i][j] = dp[i-1][j](这行不放) + dp[i-1][j-1]*(line[i]-j+1)(这行放),line[i]表示第i行的格子数。
# include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
{
LL n, m, dp1[33][1000], dp2[33][1000];
while(~scanf("%lld%lld",&n,&m),n+m)
{
memset(dp1, 0, sizeof(dp1));
memset(dp2, 0, sizeof(dp2));
dp1[0][0] = dp2[0][0] = 1LL;
int layer = 0, layer2 = 0;
for(int i=1; i<=n/2; ++i)
for(int j=1; j<=2; ++j)
{
dp1[++layer][0] = 1LL;
dp2[++layer2][0] = 1LL;
for(int k=1; k<=layer&&k<=m; ++k)
{
dp1[layer][k] = dp1[layer-1][k] + dp1[layer-1][k-1]*(layer+(layer&1)-k+1);
dp2[layer2][k] = dp2[layer2-1][k] + dp2[layer2-1][k-1]*(layer2-((layer2&1)==0)-k+1);
}
if(i == n/2 && !(n&1))
break;
}
dp2[++layer2][0] = 1LL;
for(int k=1; k<=layer2 && k<=m; ++k)
dp2[layer2][k] = dp2[layer2-1][k] + dp2[layer2-1][k-1]*(layer2-((layer2&1)==0)-k+1);
LL sum = 0;
for(int i=0; i<=m; ++i)
sum += dp1[layer][i]*dp2[layer2][m-i];
printf("%lld\n",sum);
}
return 0;
}