poj.org/problem?id=3254
采用二进制的数据表示每个方格种还是不种,然后化为十进制记录不同的状态,dp[n][m]代表第n行的第m中状态一个出现的方案个数,对于m的状态,要判断是否可以存在,并且是否有两个草地相邻,是否和第n-1行的的某种状态的草地相邻,如果相邻的话就舍弃!
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 12;
const int mod = 100000000;
int m,n;
int dp[N][1<<N],save[N];
bool CheckRow(int x){///判断是否有相邻的1
if(x & x << 1) return false;
return true;
}
bool CheckColumn(int x, int y){///判断两个数是否在相同位置有1
if(x & y) return false;
return true;
}
int main(){
// freopen("in.txt", "r", stdin);
while(scanf("%d%d",&m,&n) == 2){
memset(dp, 0, sizeof(dp));
memset(save, 0, sizeof(save));
for(int i=0; i<m; i++){
for(int j=0; j<n; j++){
int tmp;
scanf("%d",&tmp);
if(tmp) save[i] = save[i] | (1 << j);///用二进制记录一行的信息
}
}
for(int i=0; i<(1 << n); i++)///初始化第0行
if((save[0] | i) == save[0] && CheckRow(i))
dp[0][i] = 1;
for(int i=1; i<m; i++)
for(int j=0; j<(1 << n); j++)
if(CheckRow(j) && (save[i] | j) == save[i])
for(int k=0; k<(1 << n); k++)
if(CheckColumn(j, k))
dp[i][j] = (dp[i][j] + dp[i-1][k]) % mod;
int ans = 0;
for(int i=0; i<(1 << n); i++)
ans = (ans + dp[m-1][i]) % mod;
printf("%d\n",ans);
}
return 0;
}