LeetCode 857. Minimum Cost to Hire K Workers

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yixin94/article/details/82771186

题意:N个worker中选K个,每个worker有quality和wage两个属性。雇佣K个worker需要保证每个人的报酬比例和quality比例相同,而且不得低于其wage。目标是付出的报酬最小。

先考虑一个简单的情况,假设K个worker已经选定,如何定价格呢?假设有两个worker x, y, wage[x]/quality[x]<wage[y]/quality[y],那么把y的报酬设定成wage[y],x的报酬一定大于wage[x]:payment to x=quality[x]*wage[y]/quality[y]>quality[x]*wage[x]/quality[x]=wage[x]。

因此,如果K个worker已经选定,只要把wage[i]/quality[i]最高的worker(作为pivot)的payment设定成wage[i],在根据ratio算出其他worker的payment即可。

对于每个pivot worker,我们需要找出K-1个wage/quality比其小的worker而且还要让总的payment最小。wage/quality比pivot worker小的worker,一定满足payment>=wage的contraint,且total payment=wage[pivot]/quality[pivot]*sum of quality of other workers,所以我们只要保证sum of quality最小即可。

现将worker按照wage/quality从小到大排序,枚举到第i个worker作为pivot时,0~i-1 worker都是满足constraint的worker,只要从中找出K-1个quality最小的即可。

方法一:将worker不断插入有序set中,对于每个pivot worker,pop出前K小的,复杂度是KlogN,感觉会TLE。

方法二:用priority queue维护top K-1小的集合。如果新枚举的pivot worker quality比queue里面的最大元素小,那么queue.top()一定不是前K小的,所以将queue.top()移除,加入pivot worker quality。同时用sum维护top K小的quality之和,在更新queue元素时也更新sum。复杂度是logK.

另外C++ priority queue默认是大顶堆,老是记混。。

#include<iostream>
#include<stdio.h>
#include<cstdio>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<algorithm>
#include<string.h>
#include<cstring>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
#include<stack>
using namespace std;

//leetcode 857. Minimum Cost to Hire K Workers
int T;
int N;
int M;
int K;
vector<int>vec0;
vector<int>vec1;
class Solution {
public:
    bool cmp(pair<double,int>& a,pair<double,int>& b)//sort by wage/quality
    {
        return a.first<b.first;
    }
    double mincostToHireWorkers(vector<int>& quality, vector<int>& wage, int K) {
        double ans=0x3f3f3f3f;
        vector<pair<double,int> >rate;
        for(int i=0;i<quality.size();i++)
        {
            rate.push_back(make_pair(1.0*wage[i]/quality[i],i));
        }
        sort(rate.begin(),rate.end());//can not use self-defined cmp
        for(int i=0;i<rate.size();i++)
        {
            cout<<rate[i].second<<" "<<rate[i].first<<endl;
        }
        priority_queue<int>que;//maintain top K-1 largest element (exclude the pivot)
        while(!que.empty()) que.pop();
        int sum=0;
        for(int i=0;i<rate.size();i++)
        {
            cout<<i<<" "<<sum<<endl;
            if(que.size()<K-1)
            {
                que.push(quality[rate[i].second]);
                sum+=quality[rate[i].second];
            }
            else
            {
                cout<<"ans tmp "<<1.0*rate[i].first*(sum+quality[rate[i].second])<<" "<<rate[i].first<<" "<<(sum+quality[rate[i].second])<<endl;
                ans=min(ans,1.0*rate[i].first*(sum+quality[rate[i].second]));
                if(!que.empty()&&que.top()>quality[rate[i].second])
                {
                    int tmp=que.top();
                    que.push(quality[rate[i].second]);
                    que.pop();
                    sum-=tmp;
                    sum+=quality[rate[i].second];
                    cout<<"remove "<<tmp<<" push "<<quality[rate[i].second]<<endl;
                }

            }
        }
        return ans;
    }
};

int main()
{
//    priority_queue<int,vector<int>,greater<int> >que; //top is min element
//    que.push(1);
//    que.push(2);
//    que.push(3);
//    cout<<que.top()<<endl;
    freopen("input.txt","r",stdin);
    cin>>T;
    for(int ca=1;ca<=T;ca++)
    {
        cin>>N>>M>>K;
        vec0.clear();
        vec1.clear();
        for(int i=0;i<N;i++)
        {
            int tmp;
            cin>>tmp;
            vec0.push_back(tmp);
        }
        for(int i=0;i<M;i++)
        {
            int tmp;
            cin>>tmp;
            vec1.push_back(tmp);
        }
        Solution sol;
        cout<<"Case #"<<ca<<": "<<sol.mincostToHireWorkers(vec0,vec1,K)<<endl;;
    }
    return 0;
}
//4 4 2
//4 4 4 5
//13 12 13 12

猜你喜欢

转载自blog.csdn.net/yixin94/article/details/82771186