【力扣roadmap】1547. 切棍子的最小成本

21 阅读2分钟

题目描述

image.png

思路

其实这道题的示例给足了暗示。如下图所示,上面一级的答案就是cut的左区间的最小代价+cut的右区间的最小代价+当前长度。

于是,你可以胡诌出一个差不多的状态转移方程:

dp[i][j][可用cuts]=min(dp[i][cut][剩余可用cut]+dp[cut][j][剩余可用cut]+(ji)dp[i][j][可用cuts] = min(dp[i][cut][剩余可用cut] + dp[cut][j][剩余可用cut]) + (j - i )

其中,iijj表示区间的端点,第三维度记录剩余可以用的切割,这个信息将递归到下一个子问题。于是你可以写出我的第一个朴素无优化的代码。然后你发现里面怎么没开@cache?因为你把set作为状态存进去了,然而cache是unhashable,所以会报错。这一版的代码只能过12个样例。

看来不能用set来记录cuts,那怎么办呢?也好处理,你可以对cuts进行排序,然后每次传递剩余可用cuts信息的时候,只需要传递可用cuts的下标区间就行了。如果子问题发现下标区间违法,那么代表没有可用切割,直接返回代价0即可。

image.png

代码

朴素,无优化

from typing import Set 
class Solution:
    def minCost(self, n: int, cuts: List[int]) -> int:
        
        
        # @cache
        def dfs(i : int , j : int , s : Set[int] ) -> int :
            
            if j <= i : return 0 
            if len(s) == 0 :
                return 0 
            
            # 枚举 针对[i,j]应该使用哪一刀
            ans = inf
            for cut in s :
                # 使用cut cut必定存在于i和j之间
                # 让s站队
                left_s = set() 
                right_s = set() 
                for x in s :
                    if x < cut : left_s.add(x) 
                    elif x > cut : right_s.add(x) 
                ans = min(ans, dfs(i,cut,left_s) + dfs(cut,j,right_s))
            ans += j - i                
            return ans 
                
        return dfs(0,n,set(cuts))

记忆化搜索

class Solution:
    def minCost(self, n: int, cuts: List[int]) -> int:

        cuts.sort() 
        @cache
        def dfs(i : int , j : int , start_cut : int , end_cut : int ) -> int :
            
            if j <= i : return 0 
            if end_cut < start_cut : # 没有切割操作
                return 0 
            
            # 枚举 针对[i,j]应该使用哪一刀
            ans = inf
            for cut_idx in range(start_cut , end_cut + 1) :
                ans = min(ans, 
                        dfs(i,cuts[cut_idx], start_cut , cut_idx-1) \
                        + dfs( cuts[cut_idx], j,cut_idx +1 , end_cut))
            ans += j - i                
            return ans 
                
        return dfs(0,n,0,len(cuts)-1)