DP入门 leetcode题目为例

解决dp问题,关键分为两步,第一步摆出初始状态,第二步列出状态转移方程。

注意初始状态也是最优解。

 

leetcode 70.爬楼梯

初始状态,在第一层楼梯时,明显只有一种方法 F[1] = 1;在第二层楼梯时,有两种方法,F[2] = 2。

状态转移方程,可以看到,在第三层楼梯时,可以由第一层走两个,或者是在第二层走一个台阶到达,那么到达第三层楼梯的方法数目就是第一层的加上第二层的数目

以此类推,到达第i层楼梯的方法数就等于第i-1层的加上第i-2层的方法数

则状态转移方程为 F[i] = F[i-1] + F[i-2]

class Solution {
public:
    int climbStairs(int n) {

        int A[46];
        A[1]=1;  A[2]=2;
        for(int i=3;i<=n;i++){
            A[i]=A[i-1]+A[i-2];
        }
        return A[n];

    }
};

 

 

leetcode 746.使用最小花费爬楼梯

注意这道题和上一题在初始状态上就不一样,可以选择从下标为0或者下标为1的台阶开始爬楼梯,那就意味着站在下标为0或者1的台阶上的花费是0。初始状态为 F[0] = F[1] = 0

状态转移方程:在第i个台阶上,可以由第i-2个台阶上两步,此时花费是到达第i-2的台阶的最小花费加上其本身的花费;或者由第i-1个台阶上一步,此时花费是到达第i-1个台阶的最小花费加上其本身的花费。为了使花费最小,应该选择这两种状况的最小者。

则状态转移方程为 F[i] = min(F[i-1]+cost[i-1] , F[i-2]+cost[i-2] )

值得注意的是到达第i个台阶是不花费其本身第i的台阶的消耗值的

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        int A[1005];
        int length=cost.size();
        A[0]=0;
        A[1]=0;
        
        for(int i=2;i<=length;i++){
            A[i]=min((A[i-1]+cost[i-1]),A[i-2]+cost[i-2]);
        }
        return A[length];
    }
};

 leetcode 198,213.  打家劫舍

当只有一个房间时,则只需要偷走这一个房间的,初始状态A[1]=nums[0]; 如果有两个房间,则偷走两个房间中最大值的那间,初始状态A[2]=max(nums[0],nums[1]);

在第i个房间时,则考虑在偷走i-1最优下的但是不能偷走i的值  与偷走i-2的房间的最优的并且也偷走第i的房间的   这两个值的大小,选择值最大的策略。

状态转移方程: A[i] = max(A[i-1], A[i-2]+nums[i])

213(两次dp)相比198的打家劫舍,将第一家和最后一家相邻,此时只需要分别计算,进行两次dp。将第一家一直到倒数第二家算一次,第二家到倒数第一家算一次,将两个结果取最大值就是最终结果

 

leetcode 740. 删除并获得点数

先对数据进行离散,其实就是统计出以 i 为下标的值在nums中出现了几次(或者是统计出出现的和,即i*出现的次数)。举例:A[3]=4,就代表着在nums中3这个数字出现了4次。

若nums中没有的数字,在统计的列表中也就是0

在题目中描述的当获得了x的点数后,就要删除掉x-1和x+1的值,在统计后的列表中也就对应着x下标的前一项和后一项

这样对数据离散后也就将本问题转化为198 打家劫舍问题

另一种解法是,先对数据进行排序,将数据分成多个连续的小序列(这里指的是序列中相邻的两个数最大差值为1),这样对相同的数字求和传进另一个数组,对另一个数组进行打家劫舍,对多个小序列的结果相加就是最终的结果

 

leetcode 53 最大子数组和

将每一位下标的位置当做子数组中的最后一个元素的最大和,之后求得最大和的最大值

转移方程:sum[i] = max( sum[i-1]+nums[i], nums[i] )

 

leetcode 918 环形子数组的最大和

分为两种情况,最大子数组和包括首尾两端的,和最大子数组和在数组中间的,在中间的就和53一样了,在首尾两端的就相当于总和减去中间子数组最小和

极端情况,整个数组都是负数的情况下需要特殊判断,判断中间的最大子数组和小于0,则直接输出在中间的那个结果

 

posted @ 2022-02-28 22:44  预期  阅读(50)  评论(0)    收藏  举报