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;
    }
};
posted @ 2020-06-10 12:08  South1999  阅读(168)  评论(0编辑  收藏  举报