poj 3254 Corn Fields

题目解释:给你一个n*m的草地1为肥沃,0为贫瘠,现在放牛在肥沃土地上,牛不能相邻,问有多少种放法

 

用dp[i][j]表示第i行,状态为j的方案数

用位运算巧妙处理那些状态
0.用二进制数表示每一行草地的状态s[i]
1.枚举的状态符合草地的肥沃块:s[i]|k==s[i]
2.枚举的上一行状态k 不能出现连续的1:k&(k<<1)==0
3.上下两行不存在相邻的1:j&k==0

 

 

又写了一遍这个题,发现坑点主要是那几个括号,位运算和==,!=使用不加括号会死的

 比如35行39行

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<bitset>
 7 #define llint long long
 8 #define re register
 9 #define De(a) cout<<a<<endl
10 #define pau system("pause")
11 #define wline putchar('\n')
12 using namespace std;
13 const llint mod = 100000000;
14 int n,m;
15 llint dp[13][1<<12];
16 int s[13];
17 int a;
18 int main()
19 {
20     scanf("%d%d",&n,&m);
21     for(int i=1;i<=n;i++)
22     {
23         for(int j=0;j<m;j++)
24         {
25             scanf("%d",&a);
26             s[i]=(s[i]<<1)+a;
27         }
28     }
29     dp[0][0]=1;//初始化,什么也不放的状态 
30     for(int i=1;i<=n;i++)            //枚举行 
31     {
32         for(int j=0;j<(1<<m);j++)    //枚举当前行的状态 
33         {
34             if((j<<1)&j||(j>>1)&j) continue;    //剪枝:该状态不存在相邻的1 
35             if((j&s[i]) != j) continue;        //保证在肥沃土地上放牛 
36             for(int k=0;k<(1<<m);k++)
37             {
38                 if((k<<1)&k||(k>>1)&k) continue;
39                 if((j&k)==0)//符合草地的状态,且满足上下两行没有相邻的1 
40                 {
41                     dp[i][j]= (dp[i][j] + dp[i-1][k])%mod;
42                 }
43             }
44         }
45     }
46     llint ans=0;
47     for(int i=0;i<(1<<m);i++) ans = (ans + dp[n][i])%mod;
48     printf("%lld",ans);
49 }

 

 

posted @ 2018-12-04 17:22  tythen  阅读(134)  评论(0编辑  收藏  举报