【LOJ#10171】牧场的安排

一道入门的状压dp题,很有意思也很简单。

定义f[i][j]表示第i行的状态为j时,前i行的方案总数,那么答案ans=∑f[n][j].

考虑状态的转移,第i-1行的状态k能转移到第i行的j,当且仅当j&k==0且j,k分别符合他们自己放在那一行的条件,所以f[i][j]=∑f[i-1][k]  (条件符合)。

另外,位运算符的优先级很毒瘤,所以最好在运算时多加几个括号来保证运算的正确性。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 typedef long long ll;
 6 #define mod 100000000
 7 int n,m,a[15],ok[1<<13];
 8 ll f[13][1<<13];
 9 int main() {
10     scanf("%d%d",&n,&m);
11     for(int i=1;i<=n;i++) {
12         for(int j=1,x;j<=m;j++) {
13             scanf("%d",&x);
14             a[i]=a[i]*2+x;
15         }
16     }
17     for(int i=0;i<1<<m;i++)  
18         if(!((i&(i<<1))||(i&(i>>1)))) {
19             ok[i]=1;
20             if((i&a[1])==i) f[1][i]=1;
21         }
22     for(int i=2;i<=n;i++) {
23         for(int j=0;j<1<<m;j++)
24             if(ok[j]&&((j&a[i-1])==j))
25                 for(int k=0;k<1<<m;k++)
26                     if(ok[k]&&((k&a[i])==k)&&!(j&k))
27                         f[i][k]=(f[i][k]+f[i-1][j])%mod;
28     }
29     ll ans=0;
30     for(int i=0;i<1<<m;i++)    
31         ans=(ans+f[n][i])%mod;
32     printf("%lld\n",ans%mod);
33     return 0;
34 }
AC Code

 

posted @ 2019-04-13 19:46  AD_shl  阅读(254)  评论(0编辑  收藏  举报