软件公司

来源:互联网 发布:英语看图识音软件 编辑:程序博客网 时间:2024/04/29 09:35

题意

给你两种不同的工作,而每一项工作有m份。一共有n个人工作,且每个人工作两种不同的工作时间为xi,yi,问最小的时间是多少?(每个子项目必须由一个人一次完成,多个人可以同时做同一个项目中的不同子项目)

数据范围

对于30%的数据,n<=30.
对于60%的数据,n<=60.
对于100%的数据, n,m<=100.

分析

首先这题我们可以列出最基本的dp方程:f[i,j,k]=max(f[i1,js,kt],sA[i]+tB[i])表示第i个人做了j份第一项工作,k份第二项工作。明显的这样会超时O(nm4),只能过30分数据。那么我们就要从另一个角度去思考优化。我们可以从方程或题意得出这题让我们求的是每个人工作的时间的最大值最小值。咦,这不是二分吗?对!二分大法!我们就要往判定去想了,判定是判定能否在规定时间内做m份工作,这时我们很明显想到用f[i,j,k]表示能否完成,但是这样是不能从本质去解决问题的,那么就只能降维,转成f[i,j],没错可以!用f[i,j]照样可以表示,f[i,j]代表到前i个人,在1项目做了j个的情况下,2项目能做的最多的个数。转移为:f[i,j]=max(f[i,j],f[i1,jk]+(anskA[i])/B[i])最后就直接判断f[n,m]是否>=m即可。

注意

要初始化,否则会出错!

总结

这题的思想归根结底还是二分,但是方程的优化是巧妙的,能又三维转成二维。

var    n,m,l,r,ma,i,mid:longint;a:array[1..190,1..2] of longint;f:array[0..100,0..100] of longint;function max(l,r:longint):longint;begin    if l<r then exit(r) else exit(l);end;function check(x:longint):boolean;var i,j,k:longint;begin    for i:=0 to n do        for j:=0 to m do f[i,j]:=-maxlongint;    f[0,0]:=0;    for i:=1 to n do       for j:=0 to m do           for k:=0 to j do begin              if x-k*a[i,1]<0 then break;              f[i,j]:=max(f[i,j],f[i-1,j-k]+(x-k*a[i,1]) div a[i,2]);              x:=x;           end;    if f[n,m]>=m then exit(true);exit(false);end;beginassign(input,'company.in');reset(input);assign(output,'company.out');rewrite(output);    readln(n,m);    for i:=1 to n do begin read(a[i,1],a[i,2]);ma:=max(max(ma,a[i,2]),a[i,1]);end;    l:=0;r:=ma*n;    while l<r do begin       mid:=(l+r)shr 1;       if check(mid) then r:=mid else l:=mid+1;    end;    writeln(l);close(input);close(output);end.
0 0
原创粉丝点击