题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1180
题意:n个工人,两份任务A和B,每份任务被分成m份,不放A的一份为a,B的一份为b。给出每个人做a和b的时间。求干完A和B的最小时间。
思路:f[i][j]表示前i个人干A的j份最多可以干B多少分,二分答案。。。。好犀利啊。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #define max(x,y) ((x)>(y)?(x):(y)) 5 using namespace std; 6 7 int C,num=0; 8 int a[105],b[105],dp[105],n,m; 9 10 int OK(int mid) 11 { 12 int i,j,k,t; 13 memset(dp,-1,sizeof(dp)); 14 dp[0]=0; 15 for(i=1;i<=n;i++) 16 { 17 t=mid/a[i]; 18 for(j=m;j>=0;j--) for(k=0;k<=t&&k<=j;k++) if(dp[j-k]!=-1) 19 dp[j]=max(dp[j],dp[j-k]+(mid-k*a[i])/b[i]); 20 if(dp[m]>=m) break; 21 } 22 return dp[m]>=m; 23 } 24 25 int main() 26 { 27 for(scanf("%d",&C);C--;) 28 { 29 scanf("%d%d",&n,&m); 30 int i; 31 for(i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]); 32 int low=1; 33 int high=a[1]*m+b[1]*m; 34 int mid; 35 while(low<=high) 36 { 37 mid=(low+high)>>1; 38 if(OK(mid)) high=mid-1; 39 else low=mid+1; 40 } 41 printf("Case %d: ",++num); 42 if(high>=1&&OK(high)) printf("%d\n",high); 43 else printf("%d\n",low); 44 } 45 return 0; 46 }