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

题意:给定n*m格子,每个格子被染成了黑色或者白色,现在要用1*2的砖块覆盖这些格子,块与块不得重叠,且覆盖所有的白色格子,但不覆盖任意一个黑色格子,求一共有多少种覆盖方法。

思路:书上给的思路太巧妙以至于一时无法参透,于是找了一些相关的铺砖问题的解法,在此思路上改进了一下。具体思路可以参考https://blog.csdn.net/Lu597203933/article/details/44137277

这个问题在此基础上多了一个条件,即黑色格子无法被覆盖,略作改进即可。

实现代码:

#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
*/
原文地址:https://www.cnblogs.com/ZefengYao/p/8724602.html