区间dp

163 阅读1分钟
  • 特点
    • dp数组是二维的,两索引代表区间
    • 求dp数组的步骤
      • 一般两个循环起步
        • 第一个循环遍历区间长度
        • 第二个循环遍历区间左端点(结合长度可得左右端点)
        • 小到大得出结果

312. 戳气球

  • 三个问题
    • dp[i][j]代表在开区间(i,j)上能拿到的最多银币数
    • 原始数组前后加个1为了避免边界的处理,同时开区间是因为添加的两个哨兵不可以戳
    • 怎么转移?戳最后一个气球的原理,并合并之前戳过的气球
class Solution {
    public int maxCoins(int[] nums) {
        int length=nums.length;
        int[] nums2=new int[length+2];
        nums2[0]=1;
        nums2[length+1]=1;
        System.arraycopy(nums,0,nums2,1,length);
        int[][] dp=new int[length+2][length+2];
        //区间长度
        for(int len=3;len<=length+2;len++){
            //区间左端点
            for(int i=0;i<=length+2-len;i++){
                int res=0;
                //k为开区间内索引
                for(int k=i+1;k<i+len-1;k++){
                    int left=dp[i][k];
                    int right=dp[k][i+len-1];
                    res=Math.max(res,left+nums2[i]*nums2[k]*nums2[i+len-1]+right);
                }
                dp[i][i+len-1]=res;
            } 
        }
        return dp[0][length+1];
    }
}