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)