作为项目经理,你规划了一份需求的技能清单 req_skills,并打算从备选人员名单 people 中选出些人组成一个「必要团队」( 编号为 i 的备选人员 people[i] 含有一份该备选人员掌握的技能列表)。
所谓「必要团队」,就是在这个团队中,对于所需求的技能列表 req_skills 中列出的每项技能,团队中至少有一名成员已经掌握。
我们可以用每个人的编号来表示团队中的成员:例如,团队 team = [0, 1, 3] 表示掌握技能分别为 people[0],people[1],和 people[3] 的备选人员。
请你返回 任一 规模最小的必要团队,团队成员用人员编号表示。你可以按任意顺序返回答案,本题保证答案存在。
示例 1:
输入:req_skills = ["java","nodejs","reactjs"], people = [["java"],["nodejs"],["nodejs","reactjs"]]
输出:[0,2]
示例 2:
输入:req_skills = ["algorithms","math","java","reactjs","csharp","aws"], people = [["algorithms","math","java"],["algorithms","math","reactjs"],["java","csharp","aws"],["reactjs","csharp"],["csharp","math"],["aws","java"]]
输出:[1,2]
提示:
1 <= req_skills.length <= 16
1 <= people.length <= 60
1 <= people[i].length, req_skills[i].length, people[i][j].length <= 16
req_skills 和 people[i] 中的元素分别各不相同
req_skills[i][j], people[i][j][k] 都由小写英文字母组成
本题保证「必要团队」一定存在
思路:因为技能总数只有16这么大,因此我们可以考虑状压DP,分别将req_skills列表里的技能映射到二进制表示的不同位,之后通过简单的动态规划即可找到最优解,同时,本题要求输出团队成员名单,我们考虑采用map存储每一个二进制状态下所对应的列表名单。
class Solution {
public int[] smallestSufficientTeam(String[] req_skills, List> people) {
int len = people.size();
int n = req_skills.length;
int[] dp = new int[1 << n];
boolean[] flag=new boolean[1 << n];
Map map = new HashMap<>();
Map> map_list = new HashMap<>();
for (int i = 0; i < n; i++)
map.put(req_skills[i], 1 << i);
Arrays.fill(dp, 10000);
dp[0] = 0;
map_list.put(0, new HashSet<>());
for (int i = 0; i < len; i++) {
int tmp = 0;
int size = people.get(i).size();
for (int j = 0; j < size; j++) {
if (!map.containsKey(people.get(i).get(j)))
continue;
tmp |= map.get(people.get(i).get(j));
}
for (int j = 0; j < (1 << n); j++) {
if (dp[j | tmp] > dp[j] + 1) {
dp[j | tmp] = dp[j] + 1;
map_list.put(j | tmp, new HashSet<>(map_list.get(j)));
map_list.get(j | tmp).add(i);
}
}
}
int p=0;
int[] ans = new int[map_list.get((1 << n) - 1).size()];
Iterator it=map_list.get((1<