loj10170
在 n×n 的棋盘上放 k 个国王,国王可攻击相邻的 8 个格子,求使它们无法互相攻击的方案总数。
----------------------------------------------------------------------------------------------------------------------
状态压缩DP
首先选出可用的状态
然后进行动归。
f[i][s][k]:表示到第i行,第i行的状态为st[s]的情况下,放置了k个国王的方案数。
f[i][s][k]=sum(f[i-1][S][k-cs[s]]),条件是状态st[s]和st[S]不冲突。
第一次没有开LONGLONG,于是进行了替换!!比较暴力!!!
----------------------------------------------------------------------------------------------------------------------
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long n,k; 4 long long st[1<<10+5],js,cs[1<<10+5]; 5 long long f[11][1<<10+5][105]; 6 void getst(long long n) 7 { 8 for(long long i=0;i<(1<<n);++i) 9 { 10 if((i & (i<<1))==0) 11 { 12 st[js]=i; 13 long long tp=0; 14 for(long long j=0;j<n;++j) 15 if((i & (1<<j)))tp++; 16 cs[js++]=tp; 17 } 18 } 19 } 20 void dp() 21 { 22 for(long long s=0;s<js;++s)f[1][st[s]][cs[s]]=1; 23 for(long long i=2;i<=n;++i) 24 for(long long s=0;s<js;++s) 25 for(long long l=0;l<=k;++l) 26 for(long long j=0;j<js;++j) 27 if(((st[s]&st[j])==0)&&((st[s]&(st[j]>>1))==0)&&((st[s]&(st[j]<<1))==0)) 28 f[i][st[s]][l]+=f[i-1][st[j]][l-cs[s]]; 29 long long ans=0; 30 for(long long s=0;s<js;++s)ans+=f[n][st[s]][k]; 31 cout<<ans; 32 } 33 int main() 34 { 35 cin>>n>>k; 36 getst(n); 37 dp(); 38 return 0; 39 }