二分+动态规划 POJ 1973 Software Company
Software Company
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 1112 | Accepted: 482 |
Description
A software developing company has been assigned two programming projects. As both projects are within the same contract, both must be handed in at the same time. It does not help if one is finished earlier.
This company has n employees to do the jobs. To manage the two projects more easily, each is divided into m independent subprojects. Only one employee can work on a single subproject at one time, but it is possible for two employees to work on different subprojects of the same project simultaneously.
Our goal is to finish the projects as soon as possible.
This company has n employees to do the jobs. To manage the two projects more easily, each is divided into m independent subprojects. Only one employee can work on a single subproject at one time, but it is possible for two employees to work on different subprojects of the same project simultaneously.
Our goal is to finish the projects as soon as possible.
Input
The first line of the input file contains a single integer t (1 <= t <= 11), the number of test cases, followed by the input data for each test case. The first line of each test case contains two integers n (1 <= n <= 100), and m (1 <= m <= 100). The input for this test case will be followed by n lines. Each line contains two integers which specify how much time in seconds it will take for the specified employee to complete one subproject of each project. So if the line contains x and y, it means that it takes the employee x seconds to complete a subproject from the first project, and y seconds to complete a subproject from the second project.
Output
There should be one line per test case containing the minimum amount of time in seconds after which both projects can be completed.
Sample Input
1 3 20 1 1 2 4 1 6
Sample Output
18
1 /*既然动态规划方程中要转移的量太多,那么我们就把时间作为二分的对象,对时间进行二分,假设一个最短时间(每个人都不能超过的时间),进行DP,f[i][j]表示是前i个人做j个A项目所能做的最多的B项目的数目, 2 方程:d[i][j] = max { d[i][j] , d[i][j - k] + (time - A[i] * k) / B[i] } 3 枚举第i个人做k个A项目,剩下的时间用来做B项目,只要检查d[i][m]》=m就是能够到这个时间。 4 当然我们也可以用滚动数组压缩空间。*/ 5 #define N 101 6 #include<iostream> 7 using namespace std; 8 #include<cstdio> 9 #include<cstring> 10 struct QU{ 11 int n,m,A[N],B[N],f[N]; 12 void init(int x,int y) 13 { 14 n=x;m=y; 15 memset(A,0,sizeof(A)); 16 memset(B,0,sizeof(B)); 17 memset(f,0,sizeof(f)); 18 } 19 void add(int a,int b,int i) 20 { 21 A[i]=a;B[i]=b; 22 } 23 bool check(int V) 24 { 25 memset(f,-1,sizeof(f)); 26 for(int i=0;i<=m;++i) 27 {/*初始化第一个人的做i个A项目的情况*/ 28 if(i*A[1]>V) break; 29 f[i]=max(f[i],(V-i*A[1])/B[1]); 30 } 31 if(f[m]>=m) return true; 32 for(int i=2;i<=n;++i) 33 { 34 for(int j=m;j>=0;--j) 35 {/*枚举前i-1人做了多少个A*/ 36 for(int k=0;k<=j;++k) 37 {/*枚举第i个人做了k个A项目*/ 38 if(V<k*A[i]) break; 39 if(f[j-k]!=-1) 40 f[j]=max(f[j],f[j-k]+(V-k*A[i])/B[i]); 41 /*注意前-1个人可能做不到j-k个项目,这时候如果转移,那就是前i-1个人总共花了-1时间,显然不合题意*/ 42 } 43 } 44 if(f[m]>=m) return true; 45 } 46 return false; 47 } 48 }Q; 49 int main() 50 { 51 int tes; 52 scanf("%d",&tes); 53 int n,m; 54 while(tes--) 55 { 56 scanf("%d%d",&n,&m); 57 Q.init(n,m); 58 int a,b; 59 int maxx=-1; 60 for(int i=1;i<=n;++i) 61 { 62 scanf("%d%d",&a,&b); 63 Q.add(a,b,i); 64 maxx=max(maxx,max(a,b)); 65 } 66 int l=0,r=maxx*m*2; 67 int mid; 68 while(l<=r) 69 { 70 mid=(l+r)>>1; 71 if(Q.check(mid)) 72 r=mid-1; 73 else l=mid+1; 74 } 75 printf("%d\n",l); 76 77 } 78 return 0; 79 }