SRM 535 DIV1 Middle - FoxAndBusiness

問題


http://community.topcoder.com/stat?c=problem_statement&pm=11454&rd=15037

ワーカーが複数存在し、それぞれのワーカーi について以下がわかっている。
a[i]:1時間あたりにこなせる仕事の数
p[i]:仕事あたりにかかるコスト

今回、ワーカーから複数人選び、同じ時間働くように均等に仕事を割り当てる。
こなしたい仕事の数がわかっているとき、必要な最小コストを求める。

解き方


サンプル通りの計算だとワーカーiにタスクtを割り当てた時のコストは
t[i]*3600/a[i]となる。
ここで時間が均等になるようtを割り当てるのは計算が難しいので
考え方を変える。

x時間を均等に割り当てたとき、
コスト   :x*(a[i]*p[i] + a[j]*p[j]...+3600K)
タスク数:x*(a[i]+a[j]...)

単純にするために1時間の場合を考えると
コスト   :a[i]*p[i] + a[j]*p[j]...+3600K
タスク数:a[i]+a[j]...

ここで、求めたい最小のコストansは
ans/totalwork*(a[i]+a[j]...)>=a[i]*p[i] + a[j]*p[j]...+3600K
を満たす最小のansとなる。

ここで1タスクあたりの最小コストM=ans/totalworkとおくと、
M*(a[i]+a[j]...)>=a[i]*p[i] + a[j]*p[j]...+3600K

よって上記式を満たす最小のMを求め、totalWorkをかけてあげればよい。

Mは2分探索で探すことができ、
最適なワーカーはa[i]*(M-p[i])の昇順で選ぶことができる。

コード


using namespace std;

#define all(c) (c).begin(),(c).end()
#define FORE(i,d,e) for(int i=d;i<e;i++)
#define FOR(i,s,e) for (int i = int(s); i != int(e); i++)
#define FORIT(i,c) for (typeof((c).begin()) i = (c).begin(); i != (c).end(); i++)
#define ISEQ(c) (c).begin(), (c).end()

class FoxAndBusiness {

public: double minimumCost(int K, int totalWork, vector<int> a, vector<int> p) {

int n=a.size();
double low=0.0,high=1e+20;


FORE(x,0,1000){
double mid=(high+low)/2;
vector<double> vx;
FORE(i,0,n)vx.push_back(a[i]*(p[i]-mid));
sort(all(vx));

double sum=K*3600;
FORE(i,0,K)sum+=vx[i];
if(sum<=0)high=mid;
else low=mid;
}

return high*totalWork;
}

};

Share this

Related Posts

Previous
Next Post »