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);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值