公鸡5元一只,母鸡3元一只,小鸡一元3只,要求将100元刚好花光,并且刚好买100只鸡。 求:有哪几种买法,就是列出公鸡,母鸡,小鸡,各种数量的组合。
1. 穷举
假设全都买公鸡,那么公鸡的数量范围:0~20
全部买母鸡,母鸡的数量范围:0~33
小鸡的数量范围:100 - 公鸡 - 母鸡
双层遍历穷举碰结果
function resolve() {let res = []for (let i = 0, len = 20; i < len; i++) {for (let j = 0, leng = 33; j < leng; j++) {let k = 100 - i - j;if (5 * i + 3 * j + k / 3 === 100 && k % 3 === 0) {let arr = [i, j, k]res.push(arr)}}}return res}console.log(resolve())

2. 解方程
(1) x + y + z = 100 ①
(2) 5x + 3y + z/3 = 100 ②
(3) x, y, z 均为非负整数
整理
可得:
y = 25 - 7x/4,且y为非负整数;
z = 75 + 3x/4,且z为整数(z显然大于0,因为x非负)。
由于y和z必须是整数,所以x必须是4的倍数。
用单层循环即可枚举出结果(代码如下)
function resolve1() {
let res = []
for (let x = 0; x < 100; x += 4) {
if ((25 - 7 * x / 4) > 0 && (75 + 3 * x / 4) > 0) {
if (x + (25 - 7 * x / 4) + (75 + 3 * x / 4) === 100) {
let arr = [x, (25 - 7 * x / 4), (75 + 3 * x / 4)]
res.push(arr)
}
}
}
return res
}
表面上第二种方式是明显快于第一种方式的,但浏览器内部还有浏览器的编译器可能给做了某些神奇的优化,运行结果让人迷惑


测试代码
<body>
<script>
function resolve() {
let res = []
for (let i = 0, len = 20; i < len; i++) {
for (let j = 0, leng = 33; j < leng; j++) {
let k = 100 - i - j;
if (5 * i + 3 * j + k / 3 === 100 && k % 3 === 0) {
let arr = [i, j, k]
res.push(arr)
}
}
}
return res
}
function resolve1() {
let res = []
for (let x = 0; x < 100; x += 4) {
if ((25 - 7 * x / 4) > 0 && (75 + 3 * x / 4) > 0) {
if (x + (25 - 7 * x / 4) + (75 + 3 * x / 4) === 100) {
let arr = [x, (25 - 7 * x / 4), (75 + 3 * x / 4)]
res.push(arr)
}
}
}
return res
}
function calcRunTime(func,method) {
console.time('testForEach');
var res = func();
console.log('------',method,'--------')
console.log(res)
console.timeEnd('testForEach');
}
calcRunTime(resolve , 'resolve');
calcRunTime(resolve1, 'resolve1');
</script>
</body>
