Description
有一个n* m的棋盘(n、m≤80,n* m≤80)要在棋盘上放k(k≤20)个棋子,使得任意两个棋子不相邻。求合法的方案总数。
Input
n,m,k
Output
方案总数
Sample Input
3 3 2
Sample Output
24
思路
设
f
i
,
j
,
k
f_{i,j,k}
fi,j,k为第i行用第j种可行情况并放了k个棋子的方案数。
f
i
,
j
,
k
=
∑
f
i
,
p
,
k
−
j
的
棋
子
数
(
p
不
与
j
冲
突
)
(
1
<
=
i
<
=
n
,
1
<
=
j
<
=
1000
(
大
概
就
这
个
数
)
,
1
<
=
k
<
=
原
题
的
k
)
f_{i,j,k}=\sum f_{i,p,k-j的棋子数}(p不与j冲突)(1<=i<=n,1<=j<=1000(大概就这个数),1<=k<=原题的k)
fi,j,k=∑fi,p,k−j的棋子数(p不与j冲突)(1<=i<=n,1<=j<=1000(大概就这个数),1<=k<=原题的k)
code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
int a[81][(1<<9)][21],n,m,x,y,r,k,s[(1<<9)],w[(1<<9)];
void dfs(int z,int c,int y,int l)
{
if (z==m)
{
s[0]++,s[s[0]]=y,w[s[0]]=c;
return;
}
dfs(z+1,c,y<<1,0);
if (l==0) dfs(z+1,c+1,(y<<1)+1,1);
}
signed main()
{
scanf("%d%d%d",&n,&m,&k);
if (m>n) swap(m,n);
dfs(0,0,0,0);
a[0][1][0]=1;
for (int i=1;i<=n;i++) for (int j=1;j<=s[0];j++)
{
for (int kk=0;kk<=k;kk++)
{
for (int q=1;q<=s[0];q++)
{
x=s[j]&s[q];
if (x==0&&kk-w[j]>=w[q]) a[i][j][kk]+=a[i-1][q][kk-w[j]];
}
if (k==kk&&i==n) y+=a[n][j][k];
}
}
cout<<y;
return 0;
}