zoukankan      html  css  js  c++  java
  • Leetcode354. 俄罗斯套娃信封问题(线性DP/排序)

    给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现。当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。

    请计算最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。

    说明:
    不允许旋转信封。

    示例:

    输入: envelopes = [[5,4],[6,4],[6,7],[2,3]]
    输出: 3
    解释: 最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。

    没给数据范围难搞。

    首先可以看出来就是排序+DP,按x升序排列后从中选择一个子序列使得子序列中的y也是升序的,其实就是找关于y的LIS。但是直接这样求会有问题。因为最终的子序列里对于某个确定的x至多只能有一个信封的长为x,而输入数据可能会有重复的x。考虑[1, 1], [1, 2], [1, 3], [1, 4]答案应该为1,但按上述方法求就是4。这里卡了好久TAT。官方题解给的巧妙方法是按x升序排列后再按照y降序,这样求LIS的时候就能保证对于每个x只会选到一个信封了。

    LIS可以用二分查找优化。注意特判输入为空的情况。

    #include <algorithm>
    #include <algorithm>
    #include <set>
    #include <vector>
    #include <iostream>
    using namespace std;
    class Solution {
    public:
        struct env {
            int x, y, pos;
        } e[100005];
        int d[100005], len;
        static bool cmp(env a, env b) {
            if(a.x != b.x) return a.x < b.x;
            return a.y > b.y;
        }
    
        int n;
        set<env> s;
        int maxEnvelopes(vector<vector<int> >& envelopes) {
            int ans = 0;
            n = envelopes.size();
            for(int i = 0; i < envelopes.size(); i++) {
                e[i + 1].x = envelopes[i][0];
                e[i + 1].y = envelopes[i][1];
            }
            sort(e + 1, e + n + 1, cmp);
            for(int i = 1; i <= n; i++) {
                e[i].pos = i;
            }
            len = 1;
            d[1] = e[1].y;
            for(int i = 2; i <= n; i++) {
                if(d[len] < e[i].y) {
                    d[++len] = e[i].y;
                } else {
                    int pos = lower_bound(d + 1, d + len + 1, e[i].y) - d;
                    d[pos] = e[i].y;
                }
                
            }
            return len;
        }
    };
    
  • 相关阅读:
    hdu 5387 Clock (模拟)
    CodeForces 300B Coach (并查集)
    hdu 3342 Legal or Not(拓扑排序)
    hdu 3853 LOOPS(概率DP)
    hdu 3076 ssworld VS DDD(概率dp)
    csu 1120 病毒(LICS 最长公共上升子序列)
    csu 1110 RMQ with Shifts (线段树单点更新)
    poj 1458 Common Subsequence(最大公共子序列)
    poj 2456 Aggressive cows (二分)
    HDU 1869 六度分离(floyd)
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14479378.html
Copyright © 2011-2022 走看看