• 《挑战程序设计竞赛》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
    */
  • 相关阅读:
    macOS10.9+xcode6编译ffmpeg2.4.2 for ios
    [think in java]第12章 通过异常处理错误
    机房合作感受
    LeetCode 210. Course Schedule II(拓扑排序-求有向图中是否存在环)
    Java继承
    jQuery学习笔记之DOM操作、事件绑定(2)
    intellij IDEA常见操作
    log4j.properties配置详解
    jQuery学习笔记之概念(1)
    VC常用代码之创建进程
  • 原文地址:https://www.cnblogs.com/ZefengYao/p/8724602.html
Copyright © 2020-2023  润新知