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 }

 

你可能感兴趣的:(OJ)