标签:
#include<stdio.h> #include<string.h> int check(int a,int m) { int b=0; while(a>0) { if(a&1) b++; a>>=1; } if(b==m) return 1; return 0; } int main() { int n,m,dp[(1<<8)+5][10],Map1[10],s[1000],len;//dp[i][j]定义状态为在j行的状态为i char Map[10][10]; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0||m==0) { printf("0\n"); continue; } if(n==-1&&m==-1) break; for(int i=0; i<n; i++) scanf("%s",Map[i]); memset(Map1,0,sizeof(Map1)); for(int i=0; i<n; i++)//压缩地图 { for(int j=0; j<n; j++) if(Map[i][j]=='.') Map1[i]=Map1[i]|(1<<(n-1-j)); } len=0; for(int i=0; i<(1<<n); i++)//把所有的有m个1的状态存到一个数组里 if(check(i,m)) s[len++]=i; memset(dp,0,sizeof(dp)); for(int j=0;j<n;j++)//把所有为1个1的都都初始化为1,由这些点这些为只有一个1的状态去扩展,所以这个能用dp的本质是算出来所有一个情况,然后扩展成两个的情况,慢慢扩展,所以最后求一下题目要求的m的所有状态的和就行了 { for(int i=1; i<(1<<n); i=(i<<1)) if((Map1[j]&i)==0) dp[i][j]=1; } for(int i=1; i<n; i++)//枚举行 { for(int j=0; j<(1<<n); j=j==0?1:j<<1)//直接枚举当前行的状态是0,1,2,4,8.(也就是只有一个1) { if((j&Map1[i])==0)//判断是否和地图矛盾 for(int k=0; k<(1<<n); k++)//枚举上一行的状态 if((k&j)==0)//判断两个状态是否矛盾,当j==0的时候表示当前行不放,当j不等于0的时候是放在那,所以当j放一个位置的时候无论扩展到那个一个状态,都等于1*dp[k][i-1]中情况所以直接加上就行 dp[k|j][i]+=dp[k][i-1]; } } for(int i=0;i<n;i++) { for(int j=0;j<(1<<n);j++) printf("%d ",dp[j][i]); puts(""); } int ans=0; for(int i=0; i<len; i++) ans+=dp[s[i]][n-1]; printf("%d\n",ans); } return 0; } /* 4 3 #..# #.#. ..#. #.## 5 4 #..#. #.#.. ..#.. #.##. .#### 3 3 ### ### ### */ /* 5 4 #.#. ##.. .#.. ###. .### */
标签:
原文地址:http://blog.csdn.net/u013491149/article/details/43311217