【问题标题】:Can anybody explain me this brute force using bitmask任何人都可以使用位掩码向我解释这种蛮力吗
【发布时间】:2021-03-08 04:13:00
【问题描述】:

教育 Codeforces 第 105 轮的问题 A(第 2 部分的评级)。 Um_nik 用这种蛮力方法解决了这个问题,我并不完全理解。 我知道什么是位掩码,但我对 if ((mask >> (int)(s[i] - 'A')) & 1) 和 ok &= bal >= 0 感到困惑。 问题的链接是:https://codeforces.com/contest/1494/problem/A

    cin >> s;
    int n = (int)s.length();
    //cout << s << endl;
    for (int mask = 0; mask < (1 << 3); mask++) {
        int bal = 0;
        bool ok = true;
        for (int i = 0; i < n; i++) {
            if ((mask >> (int)(s[i] - 'A')) & 1)
                bal++;
            else
                bal--;
            ok &= bal >= 0;
        }
        ok &= bal == 0;
        if (ok) {
            printf("YES\n");
            return;
        }
    }
    printf("NO\n");

【问题讨论】:

  • ok &amp;= bal &gt;= 0 -> ok = ok &amp; bal &gt;= 0 -> if (bal &lt; 0) ok = false

标签: c++ algorithm brute-force bitmask


【解决方案1】:

我知道问题所在!

m的范围为0b000 ~ 0b111,第i位表示'A' + i是否为符号((如果不是,则为符号))。

例如,m = 0b010 表示{'A': ')', 'B': '(', 'C': ')'}。我需要使用m[CHAR] 来表示(m &gt;&gt; (CHAR - 'A') &amp; 1) ? '(' : ')',所以m['B'] == '('

我们知道s[i]是字符串s中的第i个字符,所以m &gt;&gt; (s[i] - 'A') &amp; 1具有m[s[i]]的含义,如果第i个字符表示符号(就会得到。

例如s = "ABBC"m = 0b010i = 2,所以s[i] == 'B',你会知道m &gt;&gt; ('B' - 'A') &amp; 1 == m['B'] == '('

最后,我们需要在开始时设置一个状态为0,如果遇到(,则添加1,如果遇到),则减去1。如果状态总是&gt;= 0,最后是== 0,那么它就有正确的答案,这就是为什么我们需要打印"YES"并返回。

【讨论】:

    【解决方案2】:

    算法背后的想法是尝试字母 A、B 和 C 的所有可能性。意思是 A 可以是 '(' 或 ')',对于 B 和 C 也是如此。

    因此我们有 8 种可能性,

    A B C   in binary
    ( ( (   0 0 0
    ( ( )   0 0 1
    ( ) (   0 1 0
    ( ) )   0 1 1
    ) ( (   1 0 0 
    ) ( )   1 0 1
    ) ) (   1 1 0
    ) ) )   1 1 1
    

    实际上,作者说 '(' is 0 and ')' is 1,或者相反,以二进制覆盖 8 种可能性,意思是从 000 到 111。为什么“或相反嗯>”?因为正如您在上面看到的,如果一个掩码为 001 提供 A:(、B:( 和 C:),那么另一个掩码 110 将呈现 A:)、B:) 和 C:(。

    因此,掩码从 0 变为 8-1 ((1 &lt;&lt; 3)-1),或者以二进制形式,从 000 变为 111。

    例如,000 表示 A、B 和 C 都是左(或右)括号,在这种情况下 110 将是))(,对于ABC(或(())。

    对于给定的掩码(外循环),内循环for (int i = 0; i &lt; n; i++) 遍历所有字符,并应用当前掩码。 (mask &gt;&gt; (int)(s[i] - 'A')) &amp; 1 只是告诉当前掩码,i 处的字母是 ( 还是 )

    也就是说,(int)(s[i] - 'A') 为 A 提供 0,为 B 提供 1,为 C 提供 2。因此,A 获取掩码的位置 0(最右边的位)位的值,B第 2nd 一个和 C 第 3rd(最左边)。

          C  B  A
    mask b2 b1 b0
    

    变量bal 可能是balance。每次遇到“开头”(() 字母时,bal 就会增加,) 会减少。

    ok &amp;= bal &gt;= 0,在内部循环中,确保在任何时候我们没有更多的结束,我们有左括号。因此,这会阻止 ABBA 获得资格。

    ok &amp;= bal == 0,在内循环之后,确保我们有相同数量的左括号和右括号。

    再次,为了避免混淆,掩码尝试了所有可能性,因此ABAB 不符合)()( 的条件,例如,掩码001,但随后掩码到达010,给出@ 987654348@符合条件。

    注意:mask 很可能从 001 (1) 开始并在 110 (6) 结束,因为 000 (0) 和 111 (7) 值永远不会工作(将所有 A、B 和 C 分配到同一个括号中是行不通的)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-01
      • 2011-08-25
      • 1970-01-01
      • 2019-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多