题目链接:http://poj.org/problem?id=3254
题目大意是有M×N的玉米地,但其中有些是不肥沃的,不能种植。用1来代表肥沃,0代表不肥沃。另外奶牛不喜欢挨着吃,也就是说要间隔着种植,求有几种种植方式,并将计算结果对1E8取模。
#include <iostream>
#include <cstdio>
using namespace std;
int dp[12][1 << 12]; // dp[i][S] := 第i行的状态为S时的方法总数
int bad[12]; // 荒地的mask
int MOD = 100000000;
int m, n;
//************************************
// Method: dfs
// FullName: dfs
// Access: public
// Returns: void
// Qualifier: 遍历一行
// Parameter: int row y坐标
// Parameter: int line x坐标
// Parameter: int S 当前集合
// Parameter: int except_S 排除集合(也就是上一行地的状态加上这一行荒地的状态)
// Parameter: int pre_dp 上一行对应的个数
//************************************
void dfs(int row, int line, int S, int except_S, int pre_dp)
{
if (line == n) // 这一行种完了,统计结果
{
dp[row][S] = (dp[row][S] + pre_dp) % MOD;
return;
}
dfs(row, line + 1, S, except_S, pre_dp); // 这一行还没有种完,继续尝试往下种
if (!(except_S & (1 << line))) // 无重叠
{
// 这里的S | 1 << line将line加入集合,except_S | (1 << (line + 1))表示排除相邻的一个
dfs(row, line + 1, S | 1 << line, except_S | (1 << (line + 1)), pre_dp);
}
}
///SubMain//
int main(int argc, char *argv[])
{
cin >> m >> n;
for (int i = 0; i < m; ++i)
{
for (int j = 0; j < n; ++j)
{
int t;
cin >> t;
bad[i] |= (!t) << j;
}
}
dfs(0, 0, 0, bad[0], 1);
for (int i = 1; i < m; ++i)
{
for (int j = 0; j < (1 << n); ++j)
{
dfs(i, 0, 0, bad[i] | j, dp[i - 1][j]); // bad[i] | j表示上一行的状态j和这一行的荒地合并加入到排除集合中
}
}
int ans = 0;
for (int i = 0; i < (1 << n); ++i)
{
ans = (ans + dp[m - 1][i]) % MOD;
}
cout << ans << endl;
return 0;
}