Corn Fields POJ - 3254

原题链接

考察:状压dp

思路:

       预处理连续1的状态,再处理能放在第i行的状态.递推时枚举pos[i]和pos[i-1]的状态即可.

注意: 位运算==的优先级高于&

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <vector>
 6 using namespace std;
 7 const int Mod = 100000000,N = 13;
 8 typedef long long ll;
 9 vector<int> v[1<<N],pos[N];
10 bool st[1<<N];
11 int mp[N],n,m;
12 ll f[N][1<<N];
13 void inits()
14 {
15     for(int i=0;i<1<<m;i++)
16     {
17         int cnt = 0;
18         for(int j=0;j<m;j++)
19         {
20             if(i>>j&1) cnt++;
21             else cnt = 0;
22             if(cnt>1) break;
23         }
24         if(cnt<2) st[i] = 1; 
25     }
26     pos[0].push_back(0);
27     for(int i=1;i<=n;i++)
28         for(int j=0;j<1<<m;j++)
29             if(st[j]&&(j|mp[i])==mp[i]) pos[i].push_back(j);
30 }
31 int main()
32 {
33     scanf("%d%d",&n,&m);
34     for(int i=1;i<=n;i++)
35       for(int j=1;j<=m;j++)
36       {
37           int x; scanf("%d",&x);
38           if(x) mp[i]|=(1<<(m-j));
39       }
40     inits();
41     f[0][0] = 1;
42     for(int i=1;i<=n;i++)
43       for(int j=0;j<pos[i].size();j++)
44           for(int k=0;k<pos[i-1].size();k++)
45               if((pos[i][j]&pos[i-1][k])==0) f[i][pos[i][j]]=(f[i][pos[i][j]]+f[i-1][pos[i-1][k]])%Mod;
46     ll ans = 0;
47     for(int i=0;i<pos[n].size();i++) ans=(ans+f[n][pos[n][i]])%Mod;
48     printf("%lld\n",ans);
49     return 0;
50 }

 

posted @ 2021-02-13 13:05  acmloser  阅读(35)  评论(0编辑  收藏  举报