POJ 3254 Corn Fields(状压DP)

【题目链接】 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;
}
原文地址:https://www.cnblogs.com/forever97/p/poj3254.html