zerojudge e527. 106 彰雲嘉區複賽 – Q7 無刻度容器倒水問題

題目在 https://zerojudge.tw/ShowProblem?problemid=e527

這題舉例很詳細, 在其x=3, y=5, z=4的案例中,出現4公升的水 (0,4)。共需要8次,其步驟可以表示如下:(3, 0) – (0, 3) – (3, 3) –(1, 5) –(1, 0) –(0, 1) –(3, 1) –(0, 4)。 但是仔細看一下,其實只要七次就可以了. 第七次的3+1也是4公升只是裝在不同容器. 所以顯然正確答案是不容許裝在不同的容器一起算. 這樣就變簡單一些.

首先我們先判斷能不能做到. 簡單的說就是z如果是x,y的最大公因數的倍數,那就有解. 不過也不能比x,y都大. 因為不容許分成兩個容器裝.

                cin >> x >> y >> z;

		if(x<y) swap(x,y);

		if (x==z || y==z){
			cout << "1" << endl;
			continue;
		}

		if (z>x || z % gcd(x, y) != 0) {
			cout << "-1" << endl;
			continue;
		}
C++

因為兩個容器不同, 可能有大有小, 可以由大的往小的倒, 反過來也可以, 不知道到底哪個比較快, 所以就兩種都算一遍. 取快的答案就可以了. X2Y( )就是計算從X往Y倒水, Y2X( )計算從Y往X倒水, 因為寫法都一樣, 所以Y2X就不用再寫一遍, 把X2Y( )的x,y參數對調, 再用X2Y( )算一遍就可以.

  	        int step1=X2Y(x, y, z);
		//cout << "X2Y="<<step1<<endl;
		int step2=X2Y(y, x, z); //x,y 對調
		//cout << "Y2X="<<step2<<endl;
		cout << (step1<step2? step1:step2) << endl;
C++

因為X,Y,Z都很小, 我就用迴圈慢慢做. 每一次迴圈, 先看X要不要補水, 再看Y要不要清空, 然侯X往Y倒, 倒多少水就看Y剩下的空間和X剩下的水量中,誰比較少.

int X2Y(int x, int y, int z){
	int count=0;
	int cur_x=0;
	int cur_y=0;
	while(cur_x!=z && cur_y!=z){
		if(cur_x==0){
			cur_x+=x;
			count++;
		}
		if(cur_y==y){
			cur_y=0;
			count++;
		}
		int diff_y=y-cur_y;
		int SubV = (diff_y<cur_x? diff_y:cur_x);
		cur_x-=SubV;
		cur_y+=SubV;
		count++;
	}
	return count;
}
C++

完整程式碼如下.

#include <iostream>
using namespace std;

int gcd(int a, int b) {
	if (b == 0) return a;
	return gcd(b, a % b);
}

int X2Y(int x, int y, int z){
	int count=0;
	int cur_x=0;
	int cur_y=0;
	while(cur_x!=z && cur_y!=z){
		if(cur_x==0){
			cur_x+=x;
			count++;
		}
		if(cur_y==y){
			cur_y=0;
			count++;
		}
		int diff_y=y-cur_y;
		int SubV = (diff_y<cur_x? diff_y:cur_x);
		cur_x-=SubV;
		cur_y+=SubV;
		count++;
	}
	return count;
}

int main() {

	int n, x, y, z;
	cin >> n;

	while(n--){

		cin >> x >> y >> z;

		if(x<y) swap(x,y);

		if (x==z || y==z){
			cout << "1" << endl;
			continue;
		}

		if (z>x || z % gcd(x, y) != 0) {
			cout << "-1" << endl;
			continue;
		}

		int step1=X2Y(x, y, z);
		//cout << "X2Y="<<step1<<endl;
		int step2=X2Y(y, x, z);
		//cout << "Y2X="<<step2<<endl;
		cout << (step1<step2? step1:step2) << endl;
		}

	return 0;
}
C++