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 }