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 }
View Code
原文地址:https://www.cnblogs.com/gryzy/p/9827380.html