两个量杯量水的问题

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)
相关文章
相关标签/搜索