Longest path in DAG. DP solution. With follow up solution.
dp[i] = max(0, dp[j] | if rectangle j can be embedded to rectangle i) + 1\n\n    public class Solution {\n        \n        boolean canFit(int[] a, int[] b) {  
**dp[i] = max(0, dp[j]** | if rectangle j can be embedded to rectangle i) **+ 1**\n\n    public class Solution {\n        \n        boolean canFit(int[] a, int[] b) {  // Rectangle a can fit into rectangle b. \n            return (a[0] < b[0] && a[1] < b[1]);\n        }\n        \n        public int maxEnvelopes(int[][] envelopes) {\n            if(envelopes == null || envelopes.length == 0) return 0;\n            // In the follow up question, rectangle can be rotated to fit into another. In this case, we need preprocess envelopes array to let smaller value be envelopes[0], bigger value be envelopes[1]\n            Arrays.sort(envelopes, (int[] x, int[] y) -> x[0] - y[0]);\n            int n = envelopes.length;\n            int dp[] = new int[n];\n            int rst = 0;\n            for(int i = 0; i < n; ++i) {\n                int max = 0;\n                for(int j = 0; j < i; ++j) {\n                    if(canFit(envelopes[j], envelopes[i])) max = Math.max(max, dp[j]);\n                }\n                dp[i] = max + 1;\n                rst = Math.max(dp[i], rst);\n            }\n            return rst;\n        }\n    }
[]