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 }