【题目链接】 http://poj.org/problem?id=3254
【题目大意】
给出一个n*m的地图,0表示不能放,问往格子上摆放上下左右不能相邻的棋子有几种方案。
【题解】
首先预处理出单行合法的情况和地图中有障碍的状态,
每次计算一行的方案时,我们枚举两种合法状态,
如果两种状态可以上下相邻则累加上一行该状态的答案。
然后累计最后一行每种状态下的答案即可.
【代码】
#include <cstdio> #include <algorithm> #include <cstring> using namespace std; const int N=15,M=1<<N,mod=100000000; int st[M],mp[M],dp[N][M],n,m,x; int main(){ while(~scanf("%d%d",&n,&m)){ memset(st,0,sizeof(st)); memset(mp,0,sizeof(mp)); memset(dp,0,sizeof(dp)); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ scanf("%d",&x); if(!x)mp[i]|=(1<<(j-1)); } }int cnt=0; for(int i=0;i<(1<<m);i++){ if(!(i&(i<<1)))st[cnt++]=i; }for(int i=0;i<cnt;i++){ if(!(mp[1]&st[i]))dp[1][i]=1; }for(int i=2;i<=n;i++){ for(int j=0;j<cnt;j++){ if(mp[i]&st[j])continue; for(int u=0;u<cnt;u++){ if(mp[i-1]&st[u])continue; if(!(st[j]&st[u]))dp[i][j]=(dp[i][j]+dp[i-1][u])%mod; } } }int ans=0; for(int i=0;i<cnt;i++)ans=(ans+dp[n][i])%mod; printf("%d ",ans); }return 0; }