leetcode_354.Russian Doll Envelopes

You have a number of envelopes with widths and heights given as a pair of integers (w, h). One envelope can fit into another if and only if both the width and height of one envelope is greater than the width and height of the other envelope.

What is the maximum number of envelopes can you Russian doll? (put one inside other)

Example:
Given envelopes = [[5,4],[6,4],[6,7],[2,3]], the maximum number of envelopes you can Russian doll is 3 ([2,3] => [5,4] => [6,7]).

题意:
这个题目意思就是给你一些二元序列,代表信封的w(宽)和h(高),当信封i和j,满足w(i) > w(j) && h(i) > h(j)时,j可装进i里面,问你最多能把多少只信封一个接一个地装进另外的信封里面。

这个题目可以用DP(动态规划)解决,最优子结构性质用反证法很好证明。具体分析如下:

  1. 为了在遍历时,确保后面的信封不能装进前面的信封里面(即保证,只允许前面的信封装进后面的信封),需将序列自定义排序。
  2. 对于第i个信封,该信封一定为前i个中最”大”的信封(即 任意 0 < j < i, w(i) >= w(j), h(i) >= h(j)),因此,我们考虑,当以i为最大的信封时,max(i)的值 ret[i],有如下状态转移方程:

    ret[i] = max(ret[j] +1) 0 < j < i && w(j) < w(i) && h(j) < h(i)
    ret[i] = 1 对于所有的 0 < j < i 都有 w(j) >= w(i) || h(j) >= h(i)

  3. 最优解 sol = max(ret[i])

具体实现代码如下:

//c++
bool cmp(pair<int, int> &a, pair<int, int> &b){
    if(a.first != b.first) return a.first < b.first;
    else return a.second < b.second;
}
class Solution {
public:
    int maxEnvelopes(vector<pair<int, int>>& envelopes) {
        sort(envelopes.begin(), envelopes.end(), cmp);
        if(envelopes.size() <= 1) return envelopes.size();
        vector<int> ret(envelopes.size(), 0);
        ret[0] = 1;
        int sol = 0;
        for(int i = 1; i < envelopes.size(); i++){
            int maxs = 0;
            for(int j = 0; j < i; j++){
                if(envelopes[i].second > envelopes[j].second && envelopes[i].first > envelopes[j].first){
                    maxs = max(maxs, ret[j] + 1);
                }
            }
            ret[i] = max(maxs, 1);
        }
        for(int i = 0; i < envelopes.size(); i++){
            sol =max(sol, ret[i]);
        }
        return sol;
    }
};
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值