美文网首页
P1228 地毯填补问题

P1228 地毯填补问题

作者: Plutorres | 来源:发表于2021-05-27 14:13 被阅读0次

    这一题其实想通了并不难,如果现在还不知道怎么做的话可以去看这里:p1228 地毯填补问题

    但是这一题在具体写代码的时候涉及到很多的编码细节问题。直接上手写,会发现要写很多相似的代码,非常繁琐。这里介绍一种表驱动的方式帮助大家简化代码,代码已经加上了注释,欢迎交流讨论。

    #include <cstdio>
    
    int dx[4] = {0, 0, 1, 1};
    int dy[4] = {0, 1, 0, 1}; 
    
    // (x0, y0) 表示左上角方格,(x, y) 表示忽略的方格,k 表示方阵大小(2^k)
    void solve(int x0, int y0, int x, int y, int k) {
        if (k == 1) {
            int _dx = x - x0;
            int _dy = y - y0;
            
            for (int i = 0; i < 4; i++) {
                if (dx[i] == _dx && dy[i] == _dy) {
                    int __dx = (_dx + 1) & 1;  // % 2(位运算速度更快)
                    int __dy = (_dy + 1) & 1;  // % 2
                    printf("%d %d %d\n", x0 + __dx, y0 + __dy, i + 1);  // 取 (x, y) 的对角方格作为地毯中点
                    return;
                }
            }
        }
        
        int p = (1 << (k - 1));
        int dx0[4] = {0, 0, p, p};
        int dy0[4] = {0, p, 0, p};
        int x1 = x0 + p - 1;
        int y1 = y0 + p - 1;
    
        bool flag = true;
        
        for (int i = 3; i >= 0; i--) {  // 从右下角开始迭代,确定 (x, y) 的位置
            int _x0 = x0 + dx0[i];  // (_x0, _y0) 表示四个左上角方格
            int _y0 = y0 + dy0[i];
            int _x1 = x1 + dx[i];   // (_x1, _y1) 表示最中间的四个方格
            int _y1 = y1 + dy[i];
            if (flag && x >= _x0 && y >= _y0) { // 确定 (x, y) 位置的判断条件(仔细体会)
                flag = false;
                solve(x1, y1, _x1, _y1, 1);     // 中间四个点也可以转化为一个子问题
                solve(_x0, _y0, x, y, k - 1);
            }
            else solve(_x0, _y0, _x1, _y1, k - 1);
        }
    }
    
    int main() {
        int k, x, y;
        scanf("%d%d%d", &k, &x, &y);
        solve(1, 1, x, y, k);
        return 0;
    }
    

    相关文章

      网友评论

          本文标题:P1228 地毯填补问题

          本文链接:https://www.haomeiwen.com/subject/xuarsltx.html