POJ3254 Corn Fields(状压DP)
题目给个n×m的地图,1可以放玉米0不可以,现在要放玉米,玉米上下左右不能相邻,问放法有几种。
当前一行的决策只会影响下一行,所以状压DP之:
- dp[i][S]表示前i行放完且第i行放玉米的列的集合是S的方案数
先预处理出每一行合法的放法的集合,合法的放法其实是很少的,通过枚举合法的集合来转移。
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 bool map[12][12]; 5 int n,m,d[12][1<<12],sta[12][1<<12],sn[12]; 6 bool isok(int x,int s){ 7 for(int i=0; i<m; ++i){ 8 if(i && ((s>>i)&1) && ((s>>i-1)&1)) return 0; 9 if(((s>>i)&1) && !map[x][i]) return 0; 10 } 11 return 1; 12 } 13 int main(){ 14 scanf("%d%d",&n,&m); 15 for(int i=0; i<n; ++i){ 16 for(int j=0; j<m; ++j) scanf("%d",&map[i][j]); 17 } 18 for(int i=0; i<n; ++i){ 19 for(int j=0; j<(1<<m); ++j){ 20 if(isok(i,j)) sta[i][sn[i]++]=j; 21 } 22 } 23 for(int i=0; i<sn[0]; ++i) d[0][sta[0][i]]=1; 24 for(int i=1; i<n; ++i){ 25 for(int j=0; j<sn[i]; ++j){ 26 for(int k=0; k<sn[i-1]; ++k){ 27 if(sta[i][j]&sta[i-1][k]) continue; 28 d[i][sta[i][j]]+=d[i-1][sta[i-1][k]]; 29 d[i][sta[i][j]]%=100000000; 30 } 31 } 32 } 33 int res=0; 34 for(int i=0; i<sn[n-1]; ++i){ 35 res+=d[n-1][sta[n-1][i]]; 36 res%=100000000; 37 } 38 printf("%d",res); 39 return 0; 40 }