1266. 玉米田
Description
农民 John 购买了一处肥沃的矩形牧场,分成M*N(1 <= M <= 12; 1 <= N <= 12)个格子。他想在那里的一些格子中种植美味的玉米。遗憾的是,有些格子区域的土地是贫瘠的,不能耕种。精明的 FJ 知道奶牛们进食时不喜欢和别的牛相邻,所以一旦在一个格子中种植玉米,那么他就不会在相邻的格子中种植,即没有两个被选中的格子拥有公共边。他还没有最终确定哪些格子要选择种植玉米。 作为一个思想开明的人,农民 John 希望考虑所有可行的选择格子种植方案。由于太开明,他还考虑一个格子都不选择的种植方案!请帮助农民 John 确定种植方案总数。
Input
Line 1: 两个用空格分隔的整数 M 和 N
Lines 2..M+1: 第 i+1 行描述牧场第i行每个格子的情况, N 个用空格分隔的整数,表示 这个格子是否可以种植(1 表示肥沃的、适合种植,0 表示贫瘠的、不可种植)
Output
Line 1: 一个整数: FJ 可选择的方案总数 除以 100,000,000 的余数。
Sample Input
2 3
1 1 1
0 1 0
Sample Output
9
分析:设f[i][j]为第i行状态为j时的方案数,f[i][j]=sum(f[i-1][k]) 其中j&k==0且j,k为合法状态。
代码
#include <cstdio>
#include <cstring>
#include <string>
#define N 20
#define M 10000
#define mo 100000000
#define ll long long
using namespace std;
int n,m;
ll ans,bin[N],a[N][M],b[N][M],f[N][M];
bool v[N];
void dfs(int x,int s,int now)
{
if (x>m)
{
b[now][++b[now][0]]=s;
return;
}
if (a[now][x]&&!v[x-1])
{
v[x]=1;
dfs(x+1,s+bin[x],now);
v[x]=0;
}
dfs(x+1,s,now);
}
int main()
{
freopen("cowfood.in","r",stdin);
freopen("cowfood.out","w",stdout);
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
bin[1]=1;
for (int i=2;i<=m;i++)
bin[i]=bin[i-1]*2;
for (int i=1;i<=n;i++)
{
memset(v,sizeof(v),0);
dfs(1,0,i);
}
for (int i=1;i<=b[1][0];i++)
f[1][b[1][i]]=1;
for (int i=2;i<=n;i++)
for (int j=1;j<=b[i][0];j++)
for (int k=1;k<=b[i-1][0];k++)
if ((b[i][j]&b[i-1][k])==0) f[i][b[i][j]]=(f[i][b[i][j]]+f[i-1][b[i-1][k]])%mo;
for (int i=1;i<=b[n][0];i++)
ans=(ans+f[n][b[n][i]])%mo;
printf("%lld",ans);
fclose(stdin);
fclose(stdout);
}