http://poj.org/problem?id=3254
Description
Farmer John has purchased a lush new rectangular pasture composed of M by N (1 ≤ M ≤ 12; 1 ≤ N ≤ 12) square parcels. He wants to grow some yummy corn for the cows on a number of squares. Regrettably, some of the squares are infertile and can't be planted. Canny FJ knows that the cows dislike eating close to each other, so when choosing which squares to plant, he avoids choosing squares that are adjacent; no two chosen squares share an edge. He has not yet made the final choice as to which squares to plant.
Being a very open-minded man, Farmer John wants to consider all possible options for how to choose the squares for planting. He is so open-minded that he considers choosing no squares as a valid option! Please help Farmer John determine the number of ways he can choose the squares to plant.
Input
Lines 2.. M+1: Line i+1 describes row i of the pasture with N space-separated integers indicating whether a square is fertile (1 for fertile, 0 for infertile)
Output
Sample Input
2 3 1 1 1 0 1 0
Sample Output
9
Hint
1 2 3 4
There are four ways to plant only on one squares (1, 2, 3, or 4), three ways to plant on two squares (13, 14, or 34), 1 way to plant on three squares (134), and one way to plant on no squares. 4+3+1+1=9.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
int dp[15][1000];
int play[1000];///可行状态
int mp[15];///输入状态
int m,n;
int ant;
bool ok(int x)
{
if(x&x<<1)return false;
return true;
}
void init()
{
ant=0;
for(int i=0; i<(1<<n); i++)
{
if(ok(i))///相邻两位同时为1
{
play[ant++]=i;///加入可行数组
}
}
}
bool fit(int x,int y)
{
if(x&y)return false;
return true;
}
int main()
{
int x;
scanf("%d%d",&m,&n);
init();///找可行状态
for(int i=0; i<m; i++)
{
mp[i]=0;
for(int j=0; j<n; j++)
{
scanf("%d",&x);
///为了方便判断和计算,我们考虑将行状态取反,
///即0表示肥沃,1表示不肥沃,这样只有当行种植状态(可行状态)和行状态相位与为0(可以模拟一下),
///这个种植状态才在该行有效,因为如果种在了不肥沃的格子上,相位与会保留位1,结果不为0。
if(x==0)
{
mp[i]+=pow(2,n-j-1);///输入状态
}
}
}
memset(dp,0,sizeof(dp));
for(int i=0; i<ant; i++)
{
if(fit(play[i],mp[0]))dp[0][i]=1;
}
for(int i=1; i<m; i++)
{
for(int j=0; j<ant; j++)
{
for(int k=0; k<ant; k++)
{
///找可行的上下两行的状态和可行的种植状态与输入状态
if(fit(play[j],play[k])&&fit(mp[i],play[j]))dp[i][j]=(dp[i][j]+dp[i-1][k])%100000000;
}
}
}
int ans=0;
for(int i=0; i<ant; i++)
{
ans=(ans+dp[m-1][i])%100000000;
}
printf("%d\n",ans);
return 0;
}