题意:
一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,
可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,
即牛与牛不能相邻。问有多少种放牛方案(一头牛都不放也是一种方案)
dp[i][j]表示第i行状态为j是方案数;
首先:找出一行中没有牛相邻的情况;把这些状态用二进制数表示;
然后从第一行开始往下递推:
从第i-1行里找出所有满足能在第i-1行放牧的状态(因为我们前面只是找出了不相邻的状态,
并不一定满足此状态在第i-1行可行(比如,10101这个状态满足不相邻条件,但是如果这时候
第i-1行为00000(即不能放牧)那么这个状态也就没有意义了。)
同理找出第i行每个满足条件的状态,然后判断在i-1行中满足的状态,与在i行中满足的状态
是否会出现上下相邻的情况;
转移方程:
dp[i][k] += dp[i-1][j];
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <string>
#include <deque>
#include <queue>
#include <stack>
using namespace std;
static int mod = 100000000;
int dp[13][1<<13];
int check(int x) //判断这一行是否有相邻;
{
if(x&(x<<1))
return 0;
return 1;
}
int n,m;
int map[13];
int a[1111];
int len;
void find() //把不相邻的状态存在一个数组里面:
{
int i,j,k,l;
len=0;
for (i =0; i < 1<<n; i++)
{
if(check(i))
a[len++]=i;
}
}
int main()
{
int i,j,k,l,ans=0;
while (cin >> m >> n)
{
memset(dp,0,sizeof(dp));
for (i = 0; i < m; i++)
{
map[i] = 0;
for (j = 0; j < n; j++)
{
cin>>k;
if(k==0)
{
map[i] |= (1<<j); //注意map为一维数组,将输入的每一行的每个数字组成
} //一个二进制数存入map里(这里先将每个数取反,方便后面操作)
}
}
find();
for (i = 0; i < len; i++) //初始化第一行
{
if((a[i]&map[0])==0)
dp[0][i]=1;
}
for (i = 1; i < m; i++) //逐行递推
{
for (j = 0; j < len; j++) //前一行的状态
{
for (k = 0; k < len; k++)//本行的状态
{
if (!(map[i-1]&a[j])&&!(map[i]&a[k])&&!(a[j]&a[k]))
dp[i][k] = (dp[i][k]+dp[i-1][j]) % mod;
}
}
}
ans=0;
for (i = 0; i < len; i++)
{
ans=(ans+dp[m-1][i])%mod;
}
cout<<ans<<endl;
}
}