NYOJ 229
View Code
1 /* 2 DP: 3 状态转移方程: 4 DP[i][j]记录的是 前 i 个人完成 j 个 A 工作后 还可以 完成多少 B 5 二分: 6 找到可能花费的最小时间 maxtime,和最大时间 mintime 7 midtime=(maxtime+mintime)>>1; 8 9 midtime 就相当于背包容量 10 看是否能装下 11 12 */ 13 #include<iostream> 14 #include<cstdio> 15 #include<cstring> 16 using namespace std; 17 18 const int size = 110; 19 20 int Ap[size]; 21 int Bp[size]; 22 int dps[size]; 23 int n,m; 24 25 int qmax(int x,int y) 26 { 27 return ((x)>(y))?(x):(y); 28 } 29 30 int slove(int mids) 31 { 32 int i,j,k; 33 memset(dps,-1,sizeof(dps)); 34 35 for(i=0;i<=m;++i) 36 if(mids>=i*Ap[1])dps[i]=(mids-i*Ap[1])/Bp[1]; 37 else break; 38 if(dps[m]>=m)return 1; 39 //dps[i]存放的是 前 x 个人 完成了 i 个 A 还可以完成多少个 B 40 for(i=2;i<=n;++i) 41 { 42 //for(j=0;j<=m;++j) 43 for(j=m;j>=0;--j)//必须是从大到小 因为下面要用到 dps[j-k]要用到旧值 不能先更新小的 44 { 45 for(k=0;k<=j&&k*Ap[i]<=mids;++k) 46 {//dps[]从二维优化到一维 原因:dps[]在没有更新之前存放的是 前 i-1一个完任务的信息 47 // 更新所得是 前 i 个人完任务的信息 48 if(dps[j-k]!=-1)dps[j]=qmax(dps[j],dps[j-k]+(mids-k*Ap[i])/Bp[i]); 49 } 50 } 51 if(dps[m]>=m)return 1; 52 } 53 return 0; 54 } 55 56 int main() 57 { 58 int i,t; 59 scanf("%d",&t); 60 while(t--) 61 { 62 int maxtime=0; 63 scanf("%d%d",&n,&m); 64 for(i=1;i<=n;++i) 65 { 66 scanf("%d%d",&Ap[i],&Bp[i]); 67 maxtime=qmax(maxtime,qmax(Ap[i],Bp[i])); 68 } 69 int L=0,R=maxtime*m*2; 70 while(L<R) 71 { 72 int mid=(L+R)>>1; 73 if(slove(mid))R=mid; 74 else L=mid+1; 75 } 76 printf("%d\n",L); 77 } 78 return 0; 79 }