题意:一个矩阵里有很多格子,每个格子有两种状态,可以放牧和不可以放牧,可以放牧用1表示,否则用0表示,在这块牧场放牛,要求两个相邻的方格不能同时放牛,即牛与牛不能相邻。问有多少种放牛方案(一头牛都不放也是一种方案)
思路:dp[i][s] 代表第i行状态为s(s是每个位置放与不放组成的0-1序列对应的十进制数)时所能得到的方案总数
递推方程:dp[i][s] = Σdp[i-1][f] (f为i-1行的状态)
判断状态合法的方案是,s中不能有相邻的1,s中的1必须满足题目给定矩阵,即矩阵有1的地方s可以放1,s与f不能在同一位置有1。
初始化:dp[1][s] = 0或1(代表第一行状态为s是否合法)
#include<cstring>
#include<cstdio>
#define mod 1000000000
int stk[400],top,N,M,a[15][15],dp[15][400];
inline bool checkline(int i,int x)
{
for(int j=0,pre=0;j<M;++j,pre=x&1,x/=2)
if(x&1 && !a[i][j+1]) return 0;
return 1;
}
inline bool checkline(int x)
{
for(int j=0,pre=0;j<M;++j,pre=x&1,x/=2)
if(x&1 && pre) return 0;
return 1;
}
void init()
{
memset(dp,0,sizeof(dp));
top=0;
for(int s=0;s< (1<<M) ;++s)
if(checkline(s)) stk[top++]=s;
}
int main()
{
while(~scanf("%d%d",&N,&M))
{
for(int i=1;i<=N;++i)
for(int j=1;j<=M;++j) scanf("%d",&a[i][j]);
init();
for(int j=0;j<top;++j) dp[1][j]=checkline(1,stk[j]);
for(int i=2;i<=N;++i)
for(int j=0;j<top;++j)
{
if(!checkline(i,stk[j])) continue;
for(int k=0;k<top;++k)
{
if((stk[j]&stk[k]) || !checkline(i-1,stk[k])) continue;
dp[i][j] = (dp[i][j]%mod+dp[i-1][k]%mod)%mod;
}
}
int ans=0;
for(int j=0;j<top;++j)
ans = (ans%mod+ dp[N][j]%mod)%mod;
printf("%d\n",ans);
}
return 0;
}