动态规划问题总结

Leetcode上的DP问题太多了,先把一部分比较需要思考的记录下来,之后再进行总结。

638. 大礼包

在LeetCode商店中, 有许多在售的物品。然而,也有一些大礼包,每个大礼包以优惠的价格捆绑销售一组物品。现给定每个物品的价格,每个大礼包包含物品的清单,以及待购物品清单。请输出确切完成待购清单的最低花费。每个大礼包的由一个数组中的一组数据描述,最后一个数字代表大礼包的价格,其他数字分别表示内含的其他种类物品的数量。任意大礼包可无限次购买。

示例 1:
输入:
[2,5], [[3,0,5],[1,2,10]], [3,2]
输出: 14
解释: 有A和B两种物品,价格分别为¥2和¥5。 大礼包1,你可以以¥5的价格购买3A和0B。 大礼包2, 你可以以¥10的价格购买1A和2B。 你需要购买3个A和2个B, 所以你付了¥10购买了1A和2B(大礼包2),以及¥4购买2A。

740. 删除与获得点数

给定一个整数数组 nums ,你可以对它进行一些操作。
每次操作中,选择任意一个 nums[i] ,删除它并获得 nums[i] 的点数。之后,你必须删除每个等于 nums[i] - 1 或 nums[i] + 1 的元素。
开始你拥有 0 个点数。返回你能通过这些操作获得的最大点数。

这个题目在学校的算法实验4上出现过。对于每一个数字,如果选择删除它,那么就必须删除和它相邻的所有元素。这与打家劫舍那道题很相似,只是这个题最好先把各数字及出现的次数存入哈希表中。原题已经给定了数字的范围。

class Solution {
public:
    int deleteAndEarn(vector<int>& nums) {
        if(nums.size() == 0)
            return 0;
        vector<int> dp(10000 + 1, 0);
        vector<int> table(10000 + 1, 0);
        for(auto i : nums)
            table[i]++;
        dp[1] = max(dp[0], table[1]);
        for(int i = 2; i <= 10000; i++)
        {
            dp[i] = max(dp[i - 1], i * table[i] + dp[i - 2]);
        }
        return dp[10000];
    }
};

646. 最长数对链

给出 n 个数对。 在每一个数对中,第一个数字总是比第二个数字小。
现在,我们定义一种跟随关系,当且仅当 b < c 时,数对(c, d) 才可以跟在 (a, b) 后面。我们用这种形式来构造一个数对链。给定一个对数集合,找出能够形成的最长数对链的长度。你不需要用到所有的数对,你可以以任何顺序选择其中的一些数对来构造。

由于这题在动态规划的标签下,先考虑的是DP的做法。由于输入不一定是有序的,所以要先对输入进行排序。对于数对(a, b)和(c, d),排序规则为b < d。然后定义状态dp[i]表示以第i个数对结尾所形成的数对链的长度,有dp[i] = max(dp[i], 1 + dp[j[)。其实这个做法与LIS的做法非常相似。

在网上查阅题解发现还可以用贪心来解。其实这个问题就是活动选择问题,可以套用它的解法。

class Solution {
public:
    static bool cmp(const vector<int>& p1, const vector<int>& p2)
    {
        return p1[1] < p2[1];
    }
    int findLongestChain(vector<vector<int>>& pairs) 
    {
        if(pairs.size() < 2)
            return pairs.size();
        sort(pairs.begin(), pairs.end(), cmp);
        vector<int> dp(pairs.size(), 0);
        dp[0] = 1;
        for(int i = 1; i < pairs.size(); i++)
        {
            int temp = 0;
            for(int j = 0; j < i; j++)
                if(pairs[j][1] < pairs[i][0])
                    temp = max(temp, dp[j]);
            //dp[i] = 1 + temp;
            dp[i] = max(dp[i - 1], 1 + temp);
        }
        /*int res = INT_MIN;
        for(int i = 0; i < pairs.size(); i++)
            res = max(res, dp[i]);
        return res;*/
        return dp[pairs.size() - 1];
    }
};

猜你喜欢

转载自blog.csdn.net/hlk09/article/details/81749599
今日推荐