• POJ2414 Phylogenetic Trees Inherited 状态压缩,位运算处理集合操作


    该题解题过程非常优美,通过位操作来维护一个可选字符集合.并且完成求并集和交集.

    详见代码:

    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    using namespace std;
    
    /*
    花了大半个小时看懂了这题题意:给定N个字符串,N为2的幂,每个字符串长度为L,这N个字符串
    是一棵完全二叉树的叶子节点,现在问树的内部在同样要填入长度为L的字符串的情况下,最少
    的花费是多少,根节点是什么. 花费是这样计算的:一条边两端的不同字符串在L个位置上的
    不同位置的数目. 如果已知某叶子节点为 AGA,那么我们考虑其双亲节点为AGG的话,那么这个
    花费为1,当然我们还要考虑AGG和另外一个孩子的差值以及和其双亲的差值
    
    解法:
    这题由于空间上的原因,我们最好对每一位进行一个单独的处理,而不是用多维的数组来表示
    状态. 那么对于每一位上面的字符,我们需要统计两个叶子节点推到双亲节点的状态,显然我
    们无法一次得到一个最优的双亲状态,而只能够去生成双亲的各个状态. 即双亲在子孩子不同
    的情况下可以选择哪些字符来填充该位
    例如:
           左孩子: AAG         
             右孩子: ATA    
             那么其双亲节点的首位只有一个选择,就是A,这个是可以用贪心证明的.
             第二位则有两种选择(A, T), 我们需要把这两种选择保存下来来证明来和未来的
             兄弟一起再一起推上去
             同理第三位也有两种选择,我们同样要保留(G, A)
             由于只有大写字母,我们完全可以状态压缩进行保留处理
             
             总之,此题的解法可以说是相当的精妙 
    */
    
    int N, L, T[2050];
    char code[2050][1050];
    
    int main() {
        int ret, lim; 
        while (scanf("%d %d", &N, &L), N|L) {
            ret = 0; // 用来记录花费
            lim = N << 1;
            for (int i = N; i < lim; i++) {
                scanf("%s", code[i]);
            }
            for (int p = 0; p < L; ++p) {
                for (int i = N; i < lim; ++i) {
                    T[i] = 1 << (code[i][p]-'A');
                    // 这里对每个字符的这一位进行一次二进制压缩
                }
                for (int i = N-1; i > 0; --i) {
                    int lch = i << 1, rch = i << 1 | 1;
                    T[i] = T[lch] & T[rch]; // 先对两个字符集做一个交集 
                    if (T[i] == 0) { // 说明没有相同的可选集合,通过一次花费换取更大的集合
                        T[i] = T[lch] | T[rch];
                        ++ret;
                    }
                }
                for (int i = 0; i < 26; ++i) {
                    if (T[1] & (1 << i)) {
                        putchar('A' + i);
                        break;    
                    }    
                } 
            }
            printf(" %d\n", ret); 
        }
        return 0;
    }
  • 相关阅读:
    从头到尾彻底理解KMP
    [CF1220E] Tourism
    [CF446C] DZY Loves Fibonacci Numbers
    [CF1003E] Tree Constructing
    [CF1238E] Keyboard Purchase
    [CF915E] Physical Education Lessons
    [CF788B] Weird journey
    [CF1371E2] Asterism (Hard Version)
    [CF780E] Underground Lab
    [CF372C] Watching Fireworks is Fun
  • 原文地址:https://www.cnblogs.com/Lyush/p/2857012.html
Copyright © 2020-2023  润新知