动态规划进阶理解

最近三天做了几道动态规划问题,和以往不一样,这几个动态规划状态转换不是特别的好找,使用递归又超时,真是头疼,下面先列出题目吧

首先,我再说一下为什么我们会做这个题目时候,选择了动态规划呢?除了显而易见的问题(就是一感觉就是动态规划),我们通常会发现有的问题都是很独立的,无向后性和向前性,就是说,我们问题的解决可以分开解决,比如这个题,我们找子数组,我们加入在前面分开了,我们发现,后面数组的值和前面没有任何关系,这样就可以考虑使用动态规划啦,我们也可以使用递归,虽然我一直超时!!!(但是可以加上记忆❀,这个题我记忆化没做出来~)我们找到方法以后,我们考虑到,每个子数组都可能被分割1到m次,先不用考虑子数组分割的数组会不会超出m,我们会发现,我们后面数组决定于前面数组分割次数和分割的最大值,也是说我们列出个表达式dp[i][j][k](i是我们到达的位置,j是我们循环找最小最大值的位置,k是次数)我们求解dp[i][j][m]时候,我们发现我们不用把j列出来,因为我们最后只要得到从0到i的最小最大值就可以了。因此方程为dp[i][j]=Math.min(dp[i][j],dp[j][k-1]+i位置到j位置总值)。下面我们列出代码:

    public int splitArray(int[] nums, int m) {
        int n = nums.length;
        int[][] f = new int[n + 1][m + 1];
        int[] sub = new int[n + 1];
        for (int i = 0; i <= n; i++) {
            for (int j = 0; j <= m; j++) {
                f[i][j] = Integer.MAX_VALUE;
            }
        }
        for (int i = 0; i < n; i++) {
            sub[i + 1] = sub[i] + nums[i];
        }
        f[0][0] = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                for (int k = 0; k < i; k++) {
                    f[i][j] = Math.min(f[i][j], Math.max(f[k][j - 1], sub[i] - sub[k]));
                }
            }
        }
        return f[n][m];        
    }

记得处理一下临界问题就好了。

第二道题,也是晕了,就在做出来的边缘一直徘徊,找不到突破口,这也让我想到,我们找动态方程的时候,不一定我们此时的状态就和前一次状态有关系,也可能和前面任何状态都形成状态转换方程,下面列出题目:

我们这道题状态就是找到此时状态,但是我们上一次状态是与这个时候相邻的状态,而不是规规整整的上一次的状态!所以一定要注意!下面我们列出代码:

    public int videoStitching111(int[][] clips, int T) {
        int[] dp=new int[T+1];
        Arrays.fill(dp,T);
        dp[0]=0;
        for(int i=1;i<=T;i++){
            for(int[] clip:clips){
                if(i>=clip[0]&&i<=clip[1]){
                    dp[i]=Math.min(dp[i],dp[clip[0]]+1);
                }
            }
        }
        return dp[T]==T?-1:dp[T];
    }
发布了17 篇原创文章 · 获赞 0 · 访问量 141

猜你喜欢

转载自blog.csdn.net/qq_33286699/article/details/105656241