【SSL】1383车II
Time Limit:1000MS Memory Limit:65536K
Description
有一个nm的棋盘(n、m≤80,nm≤80)要在棋盘上放k(k≤20)个棋子,使得任意两个棋子不相邻。求合法的方案总数。
Input
n,m,k
Output
方案总数
Sample Input
3 3 2
Sample Output
24
思路
s[j]为符合条件的一行状态,用DFS预处理
c[j]为s[j]中1的个数
f[i][j][k]表示第i行的状态为s[j]且前i行总共放置k个棋子
f[0][1][0]=1
f[i][j][k]=
p
=
∑
l
=
1
状
态
总
数
f
[
i
−
1
]
[
l
]
[
k
−
c
[
j
]
]
p = \sum_{l=1}^{状态总数}f[i-1][l][k-c[j]]
p=∑l=1状态总数f[i−1][l][k−c[j]]
s[j]&s[l]==0
1<=i<=n,1<=j,l<=状态总数,c[j]<=k<=K
代码
#include<iostream>
#include<cstdio>
using namespace std;
unsigned long long n,m,tot=0,s[1048576],c[1048576],f[81][100010][21];
void DFS(unsigned long long dep,unsigned long long sum,unsigned long long s1,unsigned long long t)
{
if(dep>m){s[++tot]=sum,c[tot]=s1;return;}
DFS(dep+1,sum<<1,s1,1);
if(t)DFS(dep+1,sum<<1|1,s1+1,0);
return;
}
int main()
{
ios::sync_with_stdio(false);
unsigned long long i,j,k,l,q,ans=0;
cin>>n>>m>>q;
if(n<m)swap(n,m);
DFS(1,0,0,1);
// cout<<tot<<endl;
// for(i=1;i<=tot;i++)cout<<s[i]<<' '<<c[i]<<endl;
f[0][1][0]=1;
for(i=1;i<=n;i++)
for(j=1;j<=tot;j++)
for(k=c[j];k<=q;k++)
for(l=1;l<=tot;l++)
if(!(s[j]&s[l]))
f[i][j][k]+=f[i-1][l][k-c[j]];//f[i][j][k]表示第i行的状态为s[j]且前i行总共放置k个棋子
for(i=1;i<=tot;i++)ans+=f[n][i][q];
cout<<ans<<endl;
return 0;
}