Description
Farmer John新买了一块长方形的牧场,这块牧场被划分成M列N行(1<=M<=12; 1<=N<=12),每一格都是一块正方形的土地。FJ打算在牧场上的某几格土地里种上美味的草,供他的奶牛们享用。遗憾的是,有些土地相当的贫瘠,不能用来放牧。并且,奶牛们喜欢独占一块草地的感觉,于是FJ不会选择两块相邻的土地,也就是说,没有哪两块草地有公共边。当然,FJ还没有决定在哪些土地上种草。 作为一个好奇的农场主,FJ想知道,如果不考虑草地的总块数,那么,一共有多少种种植方案可供他选择。当然,把新的牧场荒废,不在任何土地上种草,也算一种方案。请你帮FJ算一下这个总方案数。
Input
* 第1行: 两个正整数M和N,用空格隔开
* 第2..M+1行: 每行包含N个用空格隔开的整数,描述了每块土地的状态。输入的第i+1行描述了第i行的土地。所有整数均为0或1,是1的话,表示这块土地足够肥沃,0则表示这块地上不适合种草
Output
* 第1行: 输出一个整数,即牧场分配总方案数除以100,000,000的余数
感觉这是一道简单版的炮兵阵地?
很容易想到这道题的状态为dp[i][state]表示考虑到第i行了,state中的0或1表示选或没选。
接下来考虑转移,对于现在这一行的每个状态,肯定是由上一行的某个与它互相不干涉的状态转移而来,
为了判断上下互相不干涉,我们只需要两个相与值为0即可判断,
对于左右无相邻,我们可以讲当前state左移一位与当前state相与,如果为0,则说明没有相邻选中的了。
对于不在贫瘠的草上,我们可以将贫瘠的草设为1,将当前状态与草地状态相与,如果为0,则说明没有选中的在贫瘠的草上了。
最后考虑边界条件,对于开始,第0行全不选的答案为1,很套路的状态了。最终的答案便是,最后一行,所有状态的答案之和。
下附AC代码。
#include<iostream>
#include<stdio.h>
#include<string.h>
#define maxn 14
using namespace std;
typedef long long ll;
const ll mod=100000000;
ll n,m;
ll dic[maxn];
ll dp[maxn][(1<<maxn)];
ll judge1(ll now)
{
if((now&(now>>1))) return false;
return true;
}
int main()
{
scanf("%lld%lld",&n,&m);
for(ll i=0;i<n;i++)
for(ll j=0;j<m;j++)
{
ll x;
scanf("%lld",&x);
if(x==0)
dic[i]|=(1<<j);
}
dp[0][0]=1;
for(ll i=0;i<n;i++)
{
for(ll state=0;state<(1<<m);state++)
{
for(ll nex=0;nex<(1<<m);nex++)
{
if(judge1(nex) && (state&nex)==0 && (nex&dic[i])==0)
{
dp[i+1][nex]+=dp[i][state];
if(dp[i+1][nex]>=mod)
dp[i+1][nex]-=mod;
}
}
}
}
ll ans=0;
for(ll state=0;state<(1<<m);state++)
{
ans+=dp[n][state];
if(ans>mod)
ans-=mod;
}
printf("%lld\n",ans);
}