兩個量杯量水的問題

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

function fillOil(maxA,maxB,goal){
	//目標不能大於兩個容器的容量
	if (goal > maxA && goal > maxB)return;
	//目標必須是兩個容器容量最大公約數的倍數
	if (goal%gcd(maxA,maxB) != 0) {return};

	//初始化容器爲空
	var items = [{a:0,b:0,ac:"初始化 0:0"}]
	//初始化遊標
	var index = 0;

	//廣度遍歷全部可能狀況
	for(;;) {
		var A = items[index].a;
		var B = items[index].b;
		//得到這一步全部可能狀況以及操做方法
		var steps = [{a:0, b:B, ac:"把A清空"},
			{a:A,b:0, ac:"把B清空"},
			{a:maxA,b:B, ac:"把A裝滿"},
			{a:A,b:maxB, ac:"把B裝滿"},
			A+B<maxB?{a:0,b:A+B, ac:"把A的液體倒入B中"}:{a:A+B-maxB,b:maxB, ac:"把A的液體倒入B中"},
			A+B<maxA?{a:A+B,b:0, ac:"把B的液體倒入A中"}:{a:maxA,b:A+B-maxA, ac:"把B的液體倒入A中"}
		];
		var goals = steps.filter(function(item){return item.a == goal || item.b==goal})
		//發現目標,中止遍歷
		if(goals.length){
			var item = goals[0];
			item.parent = items[index];
			return item;
		}
		//把新生成而且沒有出現過的的步驟加入遍歷池
		steps.forEach(function(itemInStep){
			if (!items.some(function(item){return item.a == itemInStep.a && item.b == itemInStep.b})) {
				itemInStep.parent = items[index]
				items.push(itemInStep);
			};
		})
		index++;
	}
}

//打印操做步驟
function print(item){
	if (!item) {console.log("無解");return;};
	if (item.parent) {
		print(item.parent);
		console.log(item.ac + ",獲得 " + item.a + " : " + item.b);
	} 
	else console.log(item.ac);
}

function test(maxA, maxB, goal){
	print(fillOil(maxA,maxB,goal));
}

test(7,3,5)
相關文章
相關標籤/搜索