力扣周赛249期(下)

269 阅读2分钟

这是我参与8月更文挑战的8天,活动详情查看:8月更文挑战

1930. 长度为 3 的不同回文子序列

截屏2021-08-08 下午8.34.07.png

思路分析

通过观察我们发现,对于长度为3的回文序列,其实对我们的要求仅仅是两边的元素相同,从左右两边选择起点和终点,两者中间所包含的字符种类就是长度为3的首位元素为i的不同回文子序列的个数。

实在是没什么可说的代码也略了。

1931. 用三种不同颜色为网格涂色

截屏2021-08-08 下午9.36.35.png

思路分析

一般来说枚举法肯定是不对的,这种数据规模变化以后依旧可以分解为多个子问题的情况大概率是动态规划,比如说这道题中,在确定列的情况下,其实m - 1行,n列的个数就是m行n列的个数的子集,或者说所有m行n列满足答案条件的图形,他的前m-1行都是且仅是m-1行,n列的答案。

然而状态压缩dp我确实学的不是很明白,在这里讲解下官方答案的思路

由于m行较小,仅仅是1~5之间,所以答案以m为范围,

  1. 先计算出m行1列的可能数量
  2. 再计算出这个向量所能匹配的下一个合法向量的个数
// 预处理所有的 (mask1, mask2) 二元组,满足 mask1 和 mask2 作为相邻行时,同一列上两个格子的颜色不同
        unordered_map<int, vector<int>> adjacent;
        for (const auto& [mask1, color1]: valid) {
            for (const auto& [mask2, color2]: valid) {
                bool check = true;
                for (int i = 0; i < m; ++i) {
                    if (color1[i] == color2[i]) {
                        check = false;
                        break;
                    }
                }
                if (check) {
                    adjacent[mask1].push_back(mask2);
                }
            }
        }

这部分稍微详细说下,valid是一个十进制数字对应的颜色排列的数组,代码通过判断mask2是否存在相同位置元素相同的情况,并进而计算合法mask2的数量,来算出通过mask1的f[i]可以迭代计算的f[i+1]的数量。

  1. 最后使用f[n]层层叠加。

在这之中,状压有关的代码也仅仅是对颜色的表示时,使用3的n次幂来表示(由于只有三种颜色)颜色的诸多可能。