数位DP
本文最后更新于 170 天前,如有失效请评论区留言。

数位dp变通较大, 需要理解题意运用何种变量
eg.(变量名可以任取)

  • i : 不必多言, dp核心
  • limitHigh : 表示当前是否受到了 finish 的约束(我们要构造的数字不能超过 finish)。若为真,则第 i 位填入的数字至多为 finish[i],否则至多为 9,这个数记作 hi。如果在受到约束的情况下填了 finish[i],那么后续填入的数字仍会受到 finish 的约束。例如 finish=123,那么 i=0 填的是 1 的话,i=1 的这一位至多填 2。
  • limitLow : 表示当前是否受到了 start 的约束(我们要构造的数字不能低于 start)。若为真,则第 i 位填入的数字至少为 start[i],否则至少为 0,这个数记作 lo。如果在受到约束的情况下填了 start[i],那么后续填入的数字仍会受到 start 的约束。
  • mask : 表示前面选过的数字集合,换句话说,第 i 位要选的数字不能在 mask 中。(结合位运算)
  • isNum : 表示 i 前面的数位是否填了数字。若为假,则当前位可以跳过(不填数字),或者要填入的数字至少为 1;若为真,则要填入的数字可以从 0 开始。例如 n=123,在 i=0 时跳过的话,相当于后面要构造的是一个 99 以内的数字了,如果 i=1 不跳过,那么相当于构造一个 10 到 99 的两位数,如果 i=1 跳过,相当于构造的是一个 9 以内的数字。

下面贴几个实例:
https://leetcode.cn/problems/count-special-integers/description/

class Solution:
    def countSpecialNumbers(self, n: int) -> int:
        low, high = str(1), str(n)
        n = len(high)
        low = "0" * (n - len(low)) + low

        @cache
        def dfs(i, mask, limit_low, limit_hi, isnum):
            if i == n:
                return int(isnum)
            res = 0
            if not isnum and low[i] == "0":
                res += dfs(i + 1, mask, True, False, False)

            lo = int(low[i]) if limit_low else 0
            hi = int(high[i]) if limit_hi else 9
            l0 = 0 if isnum else 1
            for k in range(max(l0, lo), hi + 1):
                if (mask >> k & 1) == 0:
                    res += dfs(i + 1, mask | (1 << k), limit_low and k == lo, limit_hi and k == hi, True)
            return res

        return dfs(0, 0, True, True, False)

https://leetcode.cn/problems/count-the-number-of-powerful-integers/description/

class Solution:
    def numberOfPowerfulInt(self, start: int, finish: int, limit: int, s: str) -> int:
        # 如果前导零对数位和无影响(sum+0=sum),模板中的 isNum 可以省略。
        low, high = str(start), str(finish)
        n = len(high)
        low = ("0" * (n - len(low)) + low)
        # 也可以low=low.zfill(n)表示,一般都是low数位长度小,为和high长度一样,在前面加前导零
        pre = n - len(s)

        @cache
        def dfs(i, limit_low, limit_hi):
            if i == n:
                return 1
            lo = int(low[i]) if limit_low else 0
            hi = int(high[i]) if limit_hi else 9
            res = 0
            if i < pre:
                for k in range(lo, min(hi, limit) + 1):
                    res += dfs(i + 1, limit_low and k == lo, limit_hi and k == hi)
            else:
                x = int(s[i - pre])
                if lo <= x <= min(hi, limit):
                    res += dfs(i + 1, limit_low and x == lo, limit_hi and x == hi)
            return res

        return dfs(0, True, True)

https://leetcode.cn/problems/non-negative-integers-without-consecutive-ones/description/

class Solution:
    def findIntegers(self, n: int) -> int:
        @cache
        def dfs(i: int, pre1: bool, is_limit: bool) -> int:
            if i < 0:
                return 1
            up = n >> i & 1 if is_limit else 1
            res = dfs(i - 1, False, is_limit and up == 0)  # 填 0
            if not pre1 and up == 1:  # 可以填 1
                res += dfs(i - 1, True, is_limit)  # 填 1
            return res
        return dfs(n.bit_length() - 1, False, True)  # 从高位到低位
版权声明:除特殊说明,博客文章均为大块肌原创,依据CC BY-SA 4.0许可证进行授权,转载请附上出处链接及本声明。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇