There are two kinds of tasks, namely A and B. There are N workers and the i-th worker would like to finish one task A in ai minutes, one task B in bi minutes. Now you have X task A and Y task B, you want to assign each worker some tasks and finish all the tasks as soon as possible. You should note that the workers are working simultaneously.
input:In the first line there is an integer T(T<=50), indicates the number of test cases.
In each case, the first line contains three integers N(1<=N<=50), X,Y(1<=X,Y<=200). Then there are N lines, each line contain two integers ai, bi (1<=ai, bi <=1000).
output:For each test case, output “Case d: “ at first line where d is the case number counted from one, then output the shortest time to finish all the tasks.
Sample input:
3 2 2 2 1 10 10 1 2 2 2 1 1 10 10 3 3 3 2 7 5 5 7 2
Sample output:
Case 1: 2 Case 2: 4 Case 3: 6
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=3433
题目分析:
你要明白最多所需花费时间为所有人中花费时间最多的人的时间,对于这个时间,我们可以二分得到,然后用DP来验证。
详细DP验证过程,请看代码注释
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<iomanip> #include<algorithm> using namespace std; int t; int n,m,f[55][510],a[51],b[51],x,y,l,r; bool work(int p) { memset(f,-1,sizeof(f)); //每次验证之前需要把数组全部赋值为负 f[0][0]=0; for(int i=1;i<=n;i++)//枚举每一个工人 { for(int j=0;j<=x;j++)//在此处,我们做一个类似于背包问题的dp,把所需要做A时间看为背包代价 { f[i][j]=f[i-1][j]; for(int k=0;k<=j;k++)//在做j个A事件时能做的最多的B事件 { if(p-k*a[i]<0) break; if(f[i-1][j-k]!=-1) f[i][j]=max(f[i][j],f[i-1][j-k]+(p-k*a[i])/b[i]); } } } if(f[n][x]>=y) return true;//如果在做完所有A事件的时候所能做最多数量的B事件。 else return false; } int main() { scanf("%d",&t); for(int qw=1;qw<=t;qw++) { scanf("%d%d%d",&n,&x,&y); for(int i=1;i<=n;i++){scanf("%d%d",&a[i],&b[i]);} l=1,r=1000000; while(l+1<r)//二分枚举最短时间 { int mid=(l+r)/2; if(work(mid))r=mid; else l=mid; } cout<<"Case "<<qw<<": "; if(work(l))cout<<l<<endl; else cout<<r<<endl; } return 0; }