Como director del proyecto, usted planifica una lista de habilidades requeridas y planea seleccionar algunas personas req_skills
de la lista de candidatos para formar un "equipo requerido" ( el candidato numerado contiene una lista de habilidades que posee el candidato).people
i
people[i]
req_skills
El llamado "equipo necesario" es aquel equipo en el que al menos un miembro del equipo ha dominado cada habilidad enumerada en la lista de habilidades requeridas . Los miembros del equipo pueden estar representados por el número de cada persona:
- Por ejemplo, un equipo representa candidatos
team = [0, 1, 3]
con habilidades depeople[0]
,people[1]
y .people[3]
Por favor regrese al equipo más pequeño necesario indicado por el número de personal. Puede devolver respuestas en cualquier orden y los datos de la pregunta garantizan que las respuestas existen.
Ejemplo 1:
Descripción: req_skills = ["java","nodejs","reactjs"], people = [["java"],["nodejs"],["nodejs","reactjs"]]输出: [ 0,2 ]
Ejemplo 2:
Nota: req_skills = ["algoritmos","matemáticas","java","reactjs","csharp","aws"], people = [["algoritmos","matemáticas","java"],["algoritmos ","math","reactjs"],["java","csharp","aws"],["reactjs","csharp"],["csharp","math"],["aws", "java"]] 输出: [1,2]
Analizar gramaticalmente:
req_skills en representación binaria
arr1 registra la habilidad binaria dominada por la i-ésima persona (mapa)
Binario i = 0 ~ n -1
j son las personas emparejadas al atravesar arr1
f[i] + 1 < f[i | peo[j]] // f[i] más la j-ésima persona
pre[yo | personas[j]][0] = i;
pre[i | peo[j][1]] = j ; 1 es la j-ésima persona registrada
respuesta[i] = pre[idex][1];
idx = pre[idex][0] ; encuentra el predecesor
Tenga en cuenta la inicialización f[0] = 0;
Cuando el estado j es seleccionado por f[i | peoskills[j] ]= min(f[i] + 1,f[i | peoskills[j])
Debido a que es necesario registrar la ruta, es fácil escribir una especie de si
class Solution {
public:
vector<int> smallestSufficientTeam(vector<string>& req_skills, vector<vector<string>>& people) {
int n = req_skills.size();
int f[1<<17];
memset(f,0x3f3f3f,sizeof(f));
vector<int> ans;
map<string,int> m;
int pskill[62]; //记录第 i 个人的 skill
int pro[1<<17][2]; // pro[0] 记录 前驱 pro[1] 记录选的人得位置
for(int i = 0;i < req_skills.size();i++){
m[req_skills[i]] = i;
}
f[0] = 0; // 初始化
for(int i = 0;i < people.size();i++){
int cur = 0;
for(int j = 0;j < people[i].size();j++){
cur |= 1<<m[people[i][j]]; // 这里不能用 + 如果由重复 的 由被多加
}
pskill[i] = cur;
}
for(int i = 0;i < 1<<n;i++){
for(int j = 0;j < people.size();j++){
if(f[i] + 1 < f[i | pskill[j]]){
f[i | pskill[j]] = f[i] + 1;
pro[i | pskill[j]][0] = i; // 是由 第 i 个状态转化而来得
pro[i | pskill[j]][1] = j; // 转化而来得 是 在 第 i 个状态上加 第 j 个人
}
}
}
cout << f[(1<<n)-1];
for(int i = (1<<n) - 1 ;i > 0;){
ans.push_back(pro[i][1]);
i = pro[i][0];
}
return ans;
}
};
/*
req_skills 用二进制表示
arr1 记录第 i 个人得二进制掌握得skill( map)
二进制 i = 0 ~ n -1
j为遍历arr1 配对得 people
f[i] + 1 < f[i | peo[j]] // f[i] 加上 第 j个人
pre[i | peo[j]][0] = i;
pre[i | peo[j][1]] = j ; 1 为记录得第 j 个人
ans[i] = pre[idex][1];
idx = pre[idex][0] ; 找前驱
*/