Sgu 223
此题可用状态压缩来做,首先dfs出单独一行所有可能的放置状态,存入数组s(如n=3时s[1]=000,s[2]=100,s[3]=010,s[4]=001,s[5]=101),并设c[t]为s[t]中1的个数。
设f[l][t][k]是前l行已放完,第l行状态为s[t]且前l行共放置k个棋子的方法数,则
sgu223
设f[l][t][k]是前l行已放完,第l行状态为s[t]且前l行共放置k个棋子的方法数,则
f[l][t][k]=Sum{f[l-1][i][k-c[k]]},其中s[i]和s[t]需满足:s[i] and s[t]=0,且(s[i]*2) and s[t]=0,且(s[i]/2) and s[t]=0,边界条件为f[0][1][0]=1,f[0][i][j]=0(i!=1||j!=0)。
最后答案为Sum{f[n][i][k]}
考虑到本题的数据范围,f数组需用long long类型存储。
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<string.h>
4 int s[145],c[145],m,n,k;
5 long long f[11][145][101];
6 void dfs(int l, int now, int total)
7 {
8 if(l==n)
9 {
10 s[++m]=now;
11 c[m]=total;
12 return;
13 }
14 dfs(l+1,now<<1,total);
15 if(!(now&1))
16 dfs(l+1,(now<<1)|1,total+1);
17 }
18 void dp(int l, int t, int k)
19 {
20 f[l][t][k]=0;
21 for(int i=1;i<=m;++i)
22 if(k>=c[t]&&!(s[i]&s[t])&&!((s[i]>>1)&s[t])&&!((s[i]<<1)&s[t]))
23 {
24 if(f[l-1][i][k-c[t]]==-1)
25 dp(l-1,i,k-c[t]);
26 f[l][t][k]+=f[l-1][i][k-c[t]];
27 }
28 }
29 int main()
30 {
31 long long ans=0;
32 scanf("%d%d",&n,&k);
33 memset(f,0xff,sizeof(f));
34 dfs(0,0,0);
35 memset(f[0],0,sizeof(f[0]));
36 f[0][1][0]=1;
37 for(int i=1;i<=m;++i)
38 {
39 if(f[n][i][k]==-1)
40 dp(n,i,k);
41 ans+=f[n][i][k];
42 }
43 printf("%I64d\n",ans);
44 return 0;
45 }
2 #include<stdlib.h>
3 #include<string.h>
4 int s[145],c[145],m,n,k;
5 long long f[11][145][101];
6 void dfs(int l, int now, int total)
7 {
8 if(l==n)
9 {
10 s[++m]=now;
11 c[m]=total;
12 return;
13 }
14 dfs(l+1,now<<1,total);
15 if(!(now&1))
16 dfs(l+1,(now<<1)|1,total+1);
17 }
18 void dp(int l, int t, int k)
19 {
20 f[l][t][k]=0;
21 for(int i=1;i<=m;++i)
22 if(k>=c[t]&&!(s[i]&s[t])&&!((s[i]>>1)&s[t])&&!((s[i]<<1)&s[t]))
23 {
24 if(f[l-1][i][k-c[t]]==-1)
25 dp(l-1,i,k-c[t]);
26 f[l][t][k]+=f[l-1][i][k-c[t]];
27 }
28 }
29 int main()
30 {
31 long long ans=0;
32 scanf("%d%d",&n,&k);
33 memset(f,0xff,sizeof(f));
34 dfs(0,0,0);
35 memset(f[0],0,sizeof(f[0]));
36 f[0][1][0]=1;
37 for(int i=1;i<=m;++i)
38 {
39 if(f[n][i][k]==-1)
40 dp(n,i,k);
41 ans+=f[n][i][k];
42 }
43 printf("%I64d\n",ans);
44 return 0;
45 }