题意: 有一块n*m的田地,0代表贫瘠,不能种东西,1代表肥沃,问,要想种的土地两两之间没有公共边,并且不能种在贫瘠土地上一共有多少种方案,全不种也是一种方案。
思路:dp[i][j],代表第i行种植土地状态为j的土地方案数,先预处理出第一行的状态,即dp[1] [1—n],转移就是:
dp[ i ][ j ] += dp[ i - 1 ] [ k ],(k是与j没有公共边 && k内部土地没有公共边)。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int mod = 1e9,maxn = 15;
int dp[maxn][1<<maxn],a[maxn];
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j = m-1;j>=0;j--)
{
int x;
scanf("%d",&x);
if(x == 0)a[i] += (1<<j);
}
for(int s = 0; s < 1<<m; s++)
if((s&a[1])==0 && (s<<1&s)==0 && (s>>1&s)==0)dp[1][s] = 1;
for(int i=2;i<=n;i++)
for(int s=0;s<1<<m;s++)
for(int s0 = 0; s0 < 1<<m; s0++)
{
if(dp[i-1][s] && (s0&a[i]) == 0 && (s0&s) == 0 && (s0<<1&s0)==0 && (s0>>1&s0)==0)
dp[i][s0] += dp[i-1][s],dp[i][s0] %= mod;
}
ll sum = 0;
for(int i=0;i<1<<m;i++)sum += dp[n][i],sum%=mod;
printf("%d\n",sum);
}