There are three jugs with a volume of a, b and c liters. (a,
b, and c are positive integers not greater than 200). The first and the second
jug are initially empty, while the third
is completely filled with water. It is allowed to pour water
from one jug into another until either the first one is empty or the second one
is full. This operation can be performed zero, one or more times.
You are to write a program that computes the least total
amount of water that needs to be poured; so that at least one of the jugs
contains exactly d liters of water (d is a positive integer not greater than
200). If it is not possible to measure d liters this way your program should
find a smaller amount of water d' < d which is closest to d and for which d'
liters could be produced. When d' is found, your program should compute the
least total amount of poured water needed to produce d' liters in at least one
of the jugs.
Input
The first line of input contains the number of test cases. In
the next T lines, T test cases follow. Each test case is given in one line of
input containing four space separated integers - a, b, c and d.
Output
The output consists of two integers separated by a single
space. The first integer equals the least total amount (the sum of all waters
you pour from one jug to another) of poured water. The second integer equals d,
if d liters of water could be produced by such transformations, or equals the
closest smaller value d' that your program has found.
Sample
Input |
Sample
Output |
2
2 3 4 2
96 97 199 62 |
2 2
9859 62 |
题意:有三个杯子,容量一定,一开始第一二个杯子是空的,第三个杯子是满的,然后就把水倒到别的杯子,问最后能否达到最少有一个杯子里面的水有d升,问需要倒的水的数量最少多少。如果不能达到,小于d的又是最大的是多少,最少到多少数量的水能到达这个状态。
思路:我们用一个dist[a][b][c]记录到达这个状态的最小“距离”,然后就dfs就行了。
代码:
#include<iostream>
#include<queue>
#include<stdio.h>
#include<cstring>
#include<string.h>
#include<queue>
using namespace std;
const int maxn = 205;
struct State
{
State(int aa,int bb,int cc,int dd)
:a(aa) , b(bb) , c(cc) , d(dd) { }
int a , b, c;
int d;
};
bool operator < (const State & s1 , const State & s2)
{
return s1.d < s2.d;
}
int dist[maxn][maxn][maxn];
priority_queue<State> q;
int a , b , c , d;
int ans_d , ans_cost;
void dfs(int aa,int bb,int cc,int step)
{
if (dist[aa][bb][cc] <= step) return;
if (aa==d || bb==d || cc==d)
{
if (ans_d!=d) {
ans_d = d;
ans_cost = step;
}
else if (ans_cost > step)
ans_cost = step;
}
if (aa < d && aa >= ans_d) {
if (aa==ans_d) {
if (ans_cost > step)
ans_cost = step;
} else {
ans_cost = step;
ans_d = aa;
}
}
if (bb < d && bb >= ans_d) {
if (bb==ans_d) {
if (ans_cost > step)
ans_cost = step;
} else {
ans_cost = step;
ans_d = bb;
}
}
if (cc < d && cc >= ans_d) {
if (cc==ans_d) {
if (ans_cost > step)
ans_cost = step;
} else {
ans_cost = step;
ans_d = cc;
}
}
dist[aa][bb][cc] = step;
int cost;
if (aa > 0) {
cost = min(b-bb,aa);
if (bb < b) dfs(aa-cost,bb+cost,cc,step+cost);
cost = min(c-cc,aa);
if (cc < c) dfs(aa-cost,bb,cc+cost,step+cost);
}
if (bb > 0) {
cost = min(a-aa,bb);
if (aa < a) dfs(aa+cost,bb-cost,cc,step+cost);
cost = min(c-cc,bb);
if (cc < c) dfs(aa,bb-cost,cc+cost,step+cost);
}
if (cc > 0) {
cost = min(a-aa,cc);
if (aa < a) dfs(aa+cost,bb,cc-cost,step+cost);
cost = min(b-bb,cc);
if (bb < b) dfs(aa,bb+cost,cc-cost,step+cost);
}
}
int main()
{
int T; cin>>T;
while (T--)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
memset(dist,0x3f,sizeof(dist));
ans_cost = 1e9 , ans_d = 0;
dfs(0,0,c,0);
printf("%d %d\n",ans_cost,ans_d);
}
}