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 }

 

posted @ 2012-05-11 21:13  知行执行  阅读(237)  评论(0编辑  收藏  举报