zoukankan      html  css  js  c++  java
  • 题解 POJ 2985 The Pilots Brothers' refrigerator

    暴力出奇迹

    考虑将每个位置拨 (/) 不拨表示为 (1) (/) (0),那么 (n^2) 个位置的情况就可以用一个 (n^2=16) 位无符号二进制数表示。

    考虑对于一种拨开关的方案,可以用 (Theta(n^3)(n=4)) 的时间检验是否可行((Theta(n^2)) 枚举每一个位置, (Theta(n)) 进行状态翻转操作)

    考虑枚举所有拨的方案,并对于每一种方案进行检查是否可行,总时间复杂度 (Theta(2^{n^2}n^3)),由于 (n) 很小,可以通过本题。

    考虑题目要求的是最优化方案,所以还不能简单地把拨的方案从 (0)(2^{16}-1) 枚举。

    考虑先检验的方案,其二进制下的 (operatorname{popcount}) 值应当尽量的小((operatorname{popcount}) 表示一个数二进制下各位上 (1) 的个数)

    考虑对于一个表示检验顺序的数组 way(0..65535),我们在将其初始化 for (int i = 0; i < 65536; i++) way[i] = i; 后应当对其按照 (operatorname{popcount}) 值排序。

    考虑编写自定义 (operatorname{sort}) 比较函数 PopcountComp 为:

    1 bool PopcountComp(int a, int b) {
    2    return popcount(a) < popcount(b); 
    3 }
    

    如果使用 (STL) 中的 __builtin_popcount 函数,真实比赛会 (CE),因此考虑手打 popcount

    1 int Stable[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
    2 int popcountS(int a) { return Stable[a >> 4] + Stable[a & 15]; }
    3 int popcount(int a) { return popcountS(a >> 8) + popcountS(a & 255); }
    

    此程序第一行为一个手打的 0~15 的 popcount 表,popcountS 通过使用 Stable 中的数据处理 0~255 的数的 popcount 值,popcount 则通过调用 popcountS 处理 0~65535 的数的 popcount 值。
    值得一提的是,(STL) 中的 popcount 是类似的写法,不过用于查询的表的大小是 (256),从而使时间减少了一倍。

    总时间复杂度为 (Theta(2^{n^2}n^3 + 2^{n^2}log_2{(2^{n^2})}) = Theta(2^{n^2}n^3 + 2^{n^2}n^2) = Theta(2^{n^2}n^3))

    代码

    已略去头文件 & I/O优化

    //     自己选择的路,跪着也要走完。朋友们,虽然这个世界日益浮躁起来,只
    // 要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也
    // 能够保持自己的本色走下去。                               ——陈立杰
    /*************************************
     * @problem:      2965: The Pilots Brothers' refrigerator.
     * @user_name:    HKXA0933.
     * @time:         2020-06-02.
     * @language:     C++.
     * @upload_place: POJ.
    *************************************/ 
    
    char t[5];
    bool status[4][4], tmp[4][4];
    int way[65536];
    
    int Stable[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
    int popcountS(int a) { return Stable[a >> 4] + Stable[a & 15]; }
    int popcount(int a) { return popcountS(a >> 8) + popcountS(a & 255); }
    bool PopcountComp(int a, int b) { return popcount(a) < popcount(b); }
    
    bool check(int way) {
        memcpy(tmp, status, sizeof(status));
        for (int i = 0; i < 16; i++) 
            if (way & (1 << i)) {
                int x = i >> 2, y = i & 3;
                tmp[x][0] ^= 1; tmp[x][1] ^= 1; tmp[x][2] ^= 1; tmp[x][3] ^= 1;
                tmp[0][y] ^= 1; tmp[1][y] ^= 1; tmp[2][y] ^= 1; tmp[3][y] ^= 1;
                tmp[x][y] ^= 1;
            }
        for (int i = 0; i < 4; i++)
            for (int j = 0; j < 4; j++)
                if (!tmp[i][j]) return false;
        return true;
    }
    
    signed main() {
        for (int i = 0; i < 4; i++) {
            scanf("%s", t);
            for (int j = 0; j < 4; j++)
                status[i][j] = t[j] == '-';
        }
        for (int i = 0; i < 65536; i++) way[i] = i;
        sort(way, way + 65536, PopcountComp);
        for (int i = 0; i < 65536; i++)
            if (check(way[i])) {
                printf("%d
    ", popcount(way[i]));
                for (int j = 0; j < 16; j++) 
                    if (way[i] & (1 << j))
                        printf("%d %d
    ", (j >> 2) + 1, (j & 3) + 1);
                break;
            }
        return 0;
    }
    
    // Create File Date : 2020-06-02
    
  • 相关阅读:
    P4005 小 Y 和地铁
    P1039 侦探推理
    P2766 最长不下降子序列问题
    P2312 解方程
    P2169 正则表达式
    UOJ#22. 【UR #1】外星人
    UOJ#21. 【UR #1】缩进优化
    Palindromeness CodeChef
    bzoj5392 [Lydsy1806月赛]路径统计
    997D Cycles in product
  • 原文地址:https://www.cnblogs.com/hkxadpall/p/solution-POJ2985.html
Copyright © 2011-2022 走看看