LeetCode 1125 最小的必要团队
给定一个技能数组,再给定一些人和他们拥有的技能,求最少多少个人拥有的技能可以覆盖给定的所有技能。这道题比较容易想到用dp做,看到了技能最多只有16个,可以尝试用数位dp来做。把每个人拥有的技能转换成对应的数字,我这里是把一个人的技能直接合起来变成一个数字,可以加快运算,然后去求每个状态需要的最少人数,并且记录下这个状态是由哪一个状态加上哪一个人得来的,最后就像寻找路径一样即可求出需要的人的编号。
class Solution {
public:
vector<int> smallestSufficientTeam(vector<string>& req_skills, vector<vector<string>>& people) {
int sz=req_skills.size();
vector<int> peoples;
map<string,int> mp;
vector<int> ans;
int dp[1<<sz],pre[1<<sz],val[1<<sz];
memset(dp,0x3f3f3f3f,sizeof dp);
for(int i=0;i<sz;++i)
{
mp[req_skills[i]]=i;
}
for(int i=0;i<people.size();++i)
{
int sum=0;
for(int j=0;j<people[i].size();++j)
{
sum+=1<<mp[people[i][j]];
}
peoples.push_back(sum);
}
dp[0]=0;pre[0]=-1;
int maxn=1<<sz,tmp;
for(int i=0;i<maxn;++i)
{
for(int j=0;j<peoples.size();++j)
{
if(peoples[j]==0) continue;
tmp=i;
tmp|=peoples[j];
if(dp[tmp]>dp[i]+1)
{
dp[tmp]=dp[i]+1;
pre[tmp]=i;
val[tmp]=j;
}
}
}
for(int i=(1<<sz)-1;pre[i]!=-1;i=pre[i])
{
ans.push_back(val[i]);
}
return ans;
}
};