[Python3] DFS with memo & Bitmask | Prune by sort
```\nclass Solution:\n    def smallestSufficientTeam(self, req_skills: List[str], people: List[List[str]]) -> List[int]:\n        \n        n_skills = len(req_s
```\nclass Solution:\n    def smallestSufficientTeam(self, req_skills: List[str], people: List[List[str]]) -> List[int]:\n        \n        n_skills = len(req_skills)\n        n_people = len(people)\n        \n        # index skills\n        skill_map = {x: i for i, x in enumerate(req_skills)}\n        \n        # descending sort by length of skills per person\n        people = sorted([(i, x) for i, x in enumerate(people)], key=lambda x: -len(x[1]))\n        \n        # bit people skill\n        people_bit = {}\n        for i, p in people:\n            tmp = 0\n            for s in p:\n                tmp |= 1 << skill_map[s]\n            # if a person skill cannot be covered from pervious people then added\n            if all(x | tmp != x for x in people_bit): people_bit[tmp] = i \n        \n        # reverse skill set and id\n        people_bit = {v: k for k, v in people_bit.items()}\n        cands = [*people_bit.keys()]\n\n        # final answer and size for recording minimum team size\n        self.ans = None\n        self.size = float(\'inf\')\n\n        @lru_cache(None)\n        def dp(i, mask, team):\n            if mask == (1 << n_skills) - 1 and self.size > len(team):\n                self.size = len(team)\n                self.ans = team\n                return\n            if i == len(cands):\n                return\n            # if current person has skill not covered by previous included skills\n            if mask | people_bit[cands[i]] != mask:\n                dp(i + 1, mask | people_bit[cands[i]], tuple(set(team)|{cands[i]}))\n            dp(i + 1, mask, team)\n\n\n        dp(0, 0, tuple())\n        return self.ans
['Depth-First Search', 'Sorting', 'Bitmask', 'Python', 'Python3']