## 《挑战程序设计竞赛》P196 铺砖问题

#define _CRT_SECURE_NO_DEPRECATE
#include <iostream>
#include<vector>
#include<algorithm>
using namespace std;
#define N_MAX 16
#define MOD 10000000
#define INF 0x3f3f3f3f
int n, m;
char color[N_MAX][N_MAX];
int dp[N_MAX][1 << N_MAX];

bool TestFirstLine(int k) {//测试状态k是否可以作为第一列
int i = 0;
while (i<m) {
if (color[0][i] == 'x') {
if ((k >> i) & 1)i++;
else return false;
}
else {
if (!(k >> i & 1))i++;
else if (i == m - 1 || !(k >> (i + 1) & 1))return false;
else i += 2;
}
}
return true;
}
bool judge(int k, int j) {//第j行状态k是否合法,即状态k在规定黑色的格子处必须是1，否则不合法
int i = 0;
while (i<m) {
if (!(k >> i & 1) && color[j][i] == 'x')return false;
i++;
}
return true;
}

bool Testcompatible(int cur, int prev, int k) {//cur是当前状态,prev是上一次的状态
if (!judge(prev, k - 1))return false;
int i = 0;
while (i<m) {
if (!(cur >> i & 1)) {
if ((prev >> i & 1)) i++;
else return false;
}
else if (color[k][i] == 'x') {
if (prev >> i & 1)i++;
else return false;
}
else {
if (!(prev >> i & 1))i++;
else {
if (i == m - 1 ||!((cur>>(i+1)&1)&&(prev >> (i + 1))&1))return false;//!!!!!
else i += 2;
}

}
}
return true;
}

int main() {
while (cin >> n >> m) {
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
scanf(" %c", &color[i][j]);
if (m > n)swap(m, n);
memset(dp, 0, sizeof(dp));
int allstates = 1 << m;
for (int j = 0; j < allstates; j++) {
if (TestFirstLine(j))dp[0][j] = 1;
}
for (int i = 1; i < n; i++) {
for (int j = 0; j < allstates; j++) {
for (int k = 0; k < allstates; k++) {
if (!judge(j, i))continue;
if (Testcompatible(j, k, i)) {
dp[i][j] += dp[i - 1][k];
dp[i][j] %= MOD;

}
}
}
}
cout << dp[n - 1][allstates - 1] << endl;
}
return 0;
}
/*(.是白色,*是黑色)
3
3
. . .
. x .
. . .

output:2
*/

posted on 2018-04-05 22:31  ZefengYao  阅读(345)  评论(1编辑  收藏  举报