1 #include<cstdio>
2 #include<cstring>
3 #include<queue>
4 using namespace std;
5 typedef struct state STA;
6 struct state
7 {
8 int cup[3],water;
9 bool operator< (const state p)const
10 {//优先队列的核心其实在于队列内元素的排列顺序,也就是自定义变量的 < 定义
11 return this->water > p.water;
12 }
13 };
14
15 priority_queue<STA> psd;
16 const int maxn = 300;
17 int vis[maxn][maxn];//采取二维数组的原因之一是:所有状态的可能总数很少
18 int ans[maxn];
19 int maxcup[3],aimd;
20
21 int update_ans(STA& p)
22 {
23 for(int i=0;i<3;i++)
24 {
25 int t=p.cup[i];
26 if(ans[t]==-1||ans[t]>p.water)ans[t]=p.water;
27 }
28 return 0;
29 }
30
31 int bfs()
32 {
33 while(!psd.empty())psd.pop();
34 memset(vis,0,sizeof(vis));
35 memset(ans,-1,sizeof(ans));
36 scanf("%d%d%d%d",&maxcup[0],&maxcup[1],&maxcup[2],&aimd);
37 //printf("%d %d %d %d\n",maxcup[0],maxcup[1],maxcup[2],aimd);
38 STA p;
39 p.cup[0]=0;p.cup[1]=0;
40 p.water=0;p.cup[2]=maxcup[2];
41 vis[0][0]=1;
42 int d=aimd;
43 //
44 psd.push(p);
45 while(!psd.empty())
46 {
47 p=psd.top();psd.pop();
48 update_ans(p);
49 if(ans[d]>=0)break;
50 //倒水
51 for(int i=0;i<3;i++)
52 {
53 for(int k=0;k<3;k++)
54 {//i与k分别是出水杯与进水杯
55 if(i==k)continue;
56 if(p.cup[i]==0||p.cup[k]==maxcup[k])continue;
57 /*很重要的规律*/ int pour_water=min(maxcup[k],p.cup[i]+p.cup[k])-p.cup[k];
58 STA u;
59 memcpy(&u,&p,sizeof(p));
60 u.cup[i]-=pour_water;
61 u.cup[k]+=pour_water;
62 u.water+=pour_water;
63 //
64 if(!vis[u.cup[0]][u.cup[1]])
65 {//由于总水量一定,只要已知其中两个变量就能确定其状态
66 vis[u.cup[0]][u.cup[1]]=1;
67 psd.push(u);
68 }//if
69 }//in for
70 }//out for
71 }//while
72 //
73 while(d>=0)
74 {
75 if(ans[d]>=0){printf("%d %d\n",ans[d],d);break;}
76 else d--;//接近d,从现实的角度而言只能比d小
77 }
78 return 0;
79 }
80
81 int main()
82 {
83 //freopen("input.txt","r",stdin);
84 //freopen("ans.txt","w",stdout);
85 int n;
86 scanf("%d",&n);
87 //printf("n is %d\n",n);
88 while(n--)bfs();
89 return 0;
90 }