P1879 Corn Fields G (状压dp)

link

题意: 有一块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);
}

猜你喜欢

转载自blog.csdn.net/weixin_44499508/article/details/105407808