zoukankan      html  css  js  c++  java
  • POJ 1084 Square Destroyer(IDA*)

    题意:

    给定一个火柴棒拼成的方格阵,然后去掉一些火柴棒,问至少再去掉几根火柴棒能够让图中一个正方形都没有。

    思路:

    1. 由于题目中给定了 n 的范围,2 * n * (n + 1) <= 60 -> 所以能够保证所有的火柴用 __int64 的位运算表示;

    2. 问题的关键在于如何生成火柴构成的方阵,以及生成方阵之后如何去搜索;

    3. 启发式函数 h 的计算需要考量:如果删除了某个方阵的一个边,则能够保证 h(s1) <= h(s2) + C(s1, s2),其中 C(s1, s2) = 1,h(s1) - h(s2) <= 1,可以用反证法证明;

    4. 各种位运算的范围要明确,如 1<<i 前面要加上 __int64 修饰方能得到正确的结果,这和 C 语言默认长度是 32 有关;

    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int INFS = 0x7fffffff;
    
    int N, C, E, bound;
    __int64 square[100], base[6][6];
    bool succ;
    
    inline __int64 getflag(int i) {
        return ((__int64)1 << (i - 1));
    }
    
    inline int geth(int i, int j) {
        return (2 * N + 1) * (i - 1) + j;
    }
    
    inline int getv(int i, int j) {
        return (2 * N + 1) * (i - 1) + j + N;
    }
    
    void build(void) {
        C = 0;
        memset(base, 0, sizeof(base));
        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= N; j++) {
                base[i][j] |= getflag(geth(i, j)) | getflag(geth(i + 1, j));
                base[i][j] |= getflag(getv(i, j)) | getflag(getv(i, j + 1));
                square[C++] = base[i][j];
            }
        }
        for (int size = 2; size <= N; size++) {
            for (int i = 1; i + size - 1 <= N; i++) {
                for (int j = 1; j + size - 1 <= N; j++) {
                    square[C] = 0;
                    for (int a = 0; a < size; a++) {
                        for (int b = 0; b < size; b++)
                            square[C] ^= base[i+a][j+b];
                    }
                    C += 1;
                }
            }
        }
    }
    
    int dfs(__int64 state, int depth) {
        int h = 0;
        __int64 u = 0, s = state;
        for (int i = 0; i < C; i++) {
            if ((s & square[i]) == square[i]) {
                h += 1;
                s ^= square[i];
                if (u == 0)
                    u = square[i];
            }
        }
        if (h == 0) {
            succ = true;
            return depth;
        }
        if (depth + h > bound) {
            return depth + h;
        }
    
        int newbound = INFS;
        for (int i = 1; i <= E; i++) {
            if (u & getflag(i)) {
                int b = dfs(state ^ getflag(i), depth + 1);
                if (succ)
                    return b;
                newbound = min(b, newbound);
            }
        }
        return newbound;
    }
    
    int main() {
        int cases;
        scanf("%d", &cases);
        while (cases--) {
            scanf("%d", &N);
            build();
    
            E = 2 * N * (N + 1);
            int k;
            __int64 state = ((__int64)1 << E) - 1;
    
            scanf("%d", &k);
            for (int i = 0; i < k; i++) {
                int x;
                scanf("%d", &x);
                state ^= getflag(x);
            }
            
            succ = false;
            bound = 0;
            while (!succ)
                bound = dfs(state, 0);
    
            printf("%d\n", bound);
        }
        return 0;
    }
  • 相关阅读:
    JAVA动态添加枚举值
    maven仓库配置
    AWS S3 上传下载文件
    golang http client的MaxConnsPerHost限制
    redis cli的特殊用法
    go调度: 第三部分-并发
    tcmalloc的memory heap profiler
    【流数据处理】MySql/PG/Oracle+Kafka+Flink(CDC捕获) 部署及实时计算
    【概念】详解MapReduce原理
    一次失败的创业经历
  • 原文地址:https://www.cnblogs.com/kedebug/p/2977819.html
Copyright © 2011-2022 走看看