【dfs && 记忆化搜索&&区间dp】leet-312. 戳气球

有 n 个气球,编号为0 到 n - 1,每个气球上都标有一个数字,这些数字存在数组 nums 中。

现在要求你戳破所有的气球。戳破第 i 个气球,你可以获得 nums[i - 1] * nums[i] * nums[i + 1] 枚硬币。 这里的 i - 1 和 i + 1 代表和 i 相邻的两个气球的序号。如果 i - 1或 i + 1 超出了数组的边界,那么就当它是一个数字为 1 的气球。

求所能获得硬币的最大数量。示例 1:

示例 2:

输入:nums = [1,5]
输出:10

提示:

  • n == nums.length
  • 1 <= n <= 300
  • 0 <= nums[i] <= 100

在数组前后分别补上1,变成:1,1,5,1

memo[left][right] 表示在 (left,right) 开区间戳破所有气球获取的最大的硬币。很明显:答案=memo[0][n+1]

memo[left][right]= Math.max(memo[left][right], 开区间(left,right)范围内 戳破 第i个气球获取的最大的硬币); 此时i 取值[left+1,right-1]

开区间(left,right)范围内,戳破 第i个气球获取的最大的硬币= memo[left][i] +a[left]*a[i]*a[right] + memo[i][right]

memo[left][i] :已经戳破开区间(left,i)所有气球获取的最大值,

memo[i][right]:已经戳破开区间(i,right)所有气球获取的最大值,

a[left]*a[i]*a[right]:最后戳破i获取的值

迭代 i 从【left+1,right-1】获取最后戳破每个i能够获取的最大值, memo[left][right]就是这些值的max值

所以答案:

     public int maxCoins(int[] nums) {
        int n=nums.length;
        int[][] dp=new int[n+2][n+2];
        int[] a=new int[n+2];
        System.arraycopy(nums,0,a,1,nums.length);
        a[0]=1;
        a[n+1]=1;
        return dfs(a,0,n+1,new Integer[n+2][n+2]);

    }

    public int dfs(int[] a,int left,int right, Integer[][] memo){
        if(left+1==right) return 0;
        if(memo[left][right]!=null) return memo[left][right];

        int ans=0;
        for(int i=left+1;i<right;i++){ //依此最后戳破i,ans是每个i对应值的最大值
            ans=Math.max(ans,dfs(a,left,i,memo)+a[left]*a[i]*a[right]+dfs(a,i,right,memo));
        }
        memo[left][right]=ans;
        return memo[left][right];
    }

代码转成动态规划:

    public int maxCoins(int[] nums) {
        int n=nums.length;
        int[][] dp=new int[n+2][n+2];
        int[] a=new int[n+2];
        System.arraycopy(nums,0,a,1,nums.length);
        a[0]=1;
        a[n+1]=1;
        System.out.println(Arrays.toString(a));
        for(int r=1;r<n+2;r++){
            for(int l=r-1;l>=0;l--){
                if(l+1==r) dp[l][r]=0;
                else{
                    int ans=0;
                    for(int i=l+1;i<r;i++){
                        ans=Math.max(ans,dp[l][i]+a[l]*a[i]*a[r]+dp[i][r]);
                    }
                    dp[l][r]=ans;
                }
            }
        }
        return dp[0][n+1];

    }

算法笔试-动态规划系列 文章被收录于专栏

动态规划相关算法笔试题

全部评论

相关推荐

#聊聊我眼中的AI#在科技飞速发展的当下,AI&nbsp;已经成为了家喻户晓的热词,而&nbsp;DeepSeek&nbsp;的横空出世,更是在技术领域和社会各界激起了层层涟漪。DeepSeek&nbsp;的实力剖析作为一名软件开发工程师,我对&nbsp;DeepSeek&nbsp;这类&nbsp;AI&nbsp;工具的表现格外关注。在自然语言处理方面,DeepSeek&nbsp;展现出了相当强大的能力,其回答的准确性和逻辑性令人印象深刻。在专业领域的问题上,它能够快速整合大量信息,给出条理清晰的解答。例如,当询问关于复杂算法实现或者特定编程语言的疑难问题时,DeepSeek&nbsp;不仅能准确阐述关键概念,还能结合实际案例进行分析,其回答水平甚至超越了部分经验不足的从业者。而且,它对于多轮对话的理解和处理也十分出色,能够根据上下文精准把握提问者的意图,不断优化回答内容,就像与一位专业知识扎实的伙伴进行交流。职业选择与学习路径DeepSeek&nbsp;的爆红,无疑为未来的职业选择带来了深远影响。一方面,对于技术人才而言,AI&nbsp;相关岗位的需求必将持续攀升,如&nbsp;AI&nbsp;算法工程师、数据科学家等,这些岗位需要具备深厚的数学基础、编程能力以及对&nbsp;AI&nbsp;技术的深刻理解。另一方面,对于文科生来说,虽然传统的文字处理、内容创作等工作可能会受到一定冲击,但也催生了新的机遇,如&nbsp;AI&nbsp;伦理研究员、AI&nbsp;内容审核员等,这些岗位需要具备良好的人文素养和批判性思维。为了适应这种变化,在学习路径规划上,技术人应加强对机器学习、深度学习等核心课程的学习,积极参与开源项目,积累实践经验。文科生则要拓宽自己的知识面,了解&nbsp;AI&nbsp;技术的基本原理和应用场景,同时提升自己的数据分析和逻辑思维能力。AI&nbsp;助力解决实际问题在我的软件开发工作中,AI&nbsp;发挥了至关重要的作用。以往,遇到复杂的代码逻辑或者疑难&nbsp;Bug,常常需要花费大量时间查阅资料、请教他人,如今借助&nbsp;AI&nbsp;工具,很多问题都能迅速得到解决。只要我清晰地向&nbsp;AI&nbsp;描述需求和业务逻辑,它甚至可以直接帮助我开发功能模块。比如,在开发一个用户权限管理系统时,关于权限分配和验证的代码逻辑较为复杂,我将详细的业务需求告知&nbsp;AI,它很快就生成了初步的代码框架,我只需在此基础上进行微调优化,大大缩短了开发周期。更令人惊叹的是,AI&nbsp;不仅局限于软件开发领域,还能为各个行业提供帮助。医疗领域中,AI&nbsp;辅助诊断技术能帮助医生更准确地识别病症;教育领域里,AI&nbsp;个性化学习系统可以根据学生的学习情况制定专属学习计划。可以预见,未来&nbsp;AI&nbsp;的发展真的不可估量。AI&nbsp;正以不可阻挡之势改变着我们的生活和工作方式,DeepSeek&nbsp;只是其中的一个缩影。我们应积极拥抱这一变革,充分发挥&nbsp;AI&nbsp;的优势,为自己的职业发展和社会进步创造更多价值。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务