从数学角度进行分析,可以给出一个规律:A升杯子和B升的杯子可以倒出的水为 k * gcd(A, B)升, 下面我将给出一个简要的数学说明:(只考虑整数)
假设A = 5, B = 7吧,我们可以把这两个杯子等价为A = 5, B = 2, 继续等价为A = 3, B = 2, 继续等价为A = 1,B= 2, 继续等价为A = 1, B = 1, 继续等价为A = 1, 也就是说,A = 5, B = 7最后可以等价为只有一个1升的水杯,显然,可以倒出任意升的水.
假设A = 8, B =12吧,等价为A = 8, B = 4,等价为A = 4,B = 4,等价为A = 4,也就是说,可以倒出的水为 4 * k.
可以看出:上述的等价过程实际上是求A,B的最大公约数的过程(欧几里德算法).
某公司考试的那个原题是个不定项选择题,问的是27升和15升的杯子,可以倒出多少的水。答案显然是3的倍数.
某另外公司考试的那个原题是让你写出具体倒水的方案,其实也很简单,思路不多说,尽在下面的程序中:
#include<iostream>
using namespace std;
void pour(int A, int B, int target)
{
//inA, inB分别表示A,B中水的数量
int inA = 0;
int inB = 0;
int flag = 0;
while(1)
{
//假设倒水操作可在一定的while循环次数内完成
if(flag++ > 999)
{
cout << "Fail,xxxxxx" << endl;
break;
}
if(0 == inA)
{
cout << "fill A" << endl;
inA = A;
}
else
{
cout << "pour A into B" << endl;
inB += inA;
if(inB >= B)
{
inA = inB - B;
cout << "empty B" << endl;
inB = 0;
}
else
{
inA = 0;
}
} //end if(0 == inA)
if(target == inA || target == inB)
{
cout << "Succeed,OK!!!" << endl;
break;
}
}//end while(1)
}
int main()
{
int A, B, target;
cin >> A >> B >> target;
//可以证明,任何的A,B,target在该题目中都可以转成如下形式
//即:0 <= target < A < B
if(A <= 1 || B <= 0 || A >= B || target >= A)
{
cout << "Data are wrong" << endl;
return 0;
}
pour(A, B, target);
return 0;
}