目录
题目描述
输入描述
输出描述
用例
题目解析
算法源码
题目描述
羊、狼、农夫都在岸边,当羊的数量小于狼的数量时,狼会攻击羊,农夫则会损失羊。农夫有一艘容量固定的船,能够承载固定数量的动物。
要求求出不损失羊情况下将全部羊和狼运到对岸需要的最小次数。
只计算农夫去对岸的次数,回程时农夫不会运送羊和狼。
备注:农夫在或农夫离开后羊的数量大于狼的数量时狼不会攻击羊。
输入描述
第一行输入为M,N,X, 分别代表羊的数量,狼的数量,小船的容量。
输出描述
输出不损失羊情况下将全部羊和狼运到对岸需要的最小次数(若无法满足条件则输出0)。
用例
输入 | 5 3 3 |
输出 | 3 |
说明 | 第一次运2只狼 第二次运3只羊 第三次运2只羊和1只狼 |
输入 | 5 4 1 |
输出 | 0 |
说明 | 如果找不到不损失羊的运送方案,输出0 |
题目解析
本题求不损失羊的前提下,将羊和狼全部运到对岸的最小次数。
首先,要搞清楚,如何保证不损失羊?
农夫在或农夫离开后羊的数量大于狼的数量时狼不会攻击羊。
从备注可知,只有羊的数量大于狼,狼才不会攻击羊,也就不会损失羊。
现在狼和羊在一起的地方有三处:此岸,船上,对岸
也就是说,每一次运输,都要确保,此岸、正在运输的船上、对岸,三处的羊数量>狼数量。
因此,我们首先可以判断,如果初始时,羊数量 <= 狼数量,则直接返回0,即无运输方案。
如果初始时,羊数量 > 狼数量,则我们可以再判断狼数量和船载量的关系。
如果 狼数量 < 船载量,则:我们理论上,可以先将狼一波带走,然后再多次满载羊过河。
但是细化的话,还可以判断 狼数量 < 一半的船载量,则可以先把所有狼放到船上,再用羊把船填满,此时由于狼数量 < 一半船载量,因此填进去的羊数量肯定大于狼数量。这样的话,后面单独运羊的时候,就可以减少一些运次。
如果 狼数量 >= 船载量boat,则此时:
我们应该先运 boat - 1 只狼到对岸,再运 boat 只 羊到对岸,即运输两次,这样可以保证运输时船上只有羊或狼,不需要考虑谁多谁少的问题,并且狼先到对岸,由于没有羊,也不会造成损失。然后当羊运输过去时,由于有boat只羊,boat-1只狼,因此也不会损失羊。
这是第1次、第2次运输的策略。
后面的运输,我们需要让船尽量满载,这样才能保证运次是最少的。
船满载的情况下,还要保证:此岸、船上、对岸 的 羊 > 狼。
这里,我们首先,需要保证船上的羊>狼,即 boat_sheep > boat_wolf,且boat_sheep + boat_wolf = boat。这个分配很简单:
let boat_sheep = Math.ceil(boat / 2) + (boat % 2 === 0 ? 1 : 0);
let boat_wolf = boat - boat_sheep ;
但是这样只能保证船上的羊>狼,以及船到对岸后,对岸的羊>狼,不能保证此岸的羊>狼。
因此,我们在运输前,还需要判断此岸如果以上面策略运输后,此岸上的羊是否还大于狼,如果不大于,则上面策略不可行。
我们需要先运输一点此岸的狼到对岸去,让对岸的:羊数量 = 狼数量 + 1。
然后,在试试下面的分配策略
let boat_sheep = Math.ceil(boat / 2) + (boat % 2 === 0 ? 1 : 0);
let boat_wolf = boat - boat_sheep ;
如果还不行,则说明运输方案不成立,返回0。
算法源码
/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.on("line", (line) => {
const [m, n, x] = line.split(" ").map(Number);
console.log(getResult(m, n, x));
});
function getResult(sheep, wolf, boat) {
if (sheep <= wolf) return 0;
if (sheep + wolf <= boat) return 1;
if (wolf < boat) {
if (wolf < Math.floor(boat / 2)) sheep -= boat - wolf;
return Math.ceil(sheep / boat) + 1;
}
if (wolf >= boat) {
wolf -= boat - 1;
let wolf_opposite = boat - 1;
sheep -= boat;
let sheep_opposite = boat;
if (sheep <= wolf) return 0;
let transport = 2;
let max = Math.ceil(boat / 2) + (boat % 2 === 0 ? 1 : 0);
let min = boat - max;
while (sheep > 0) {
// console.log(sheep, wolf, sheep_opposite, wolf_opposite, "|", transport);
if (sheep - max > wolf - min || (sheep === max && wolf === min)) {
sheep -= max;
sheep_opposite += max;
wolf -= min;
wolf_opposite += min;
transport++;
} else {
let tmp = sheep_opposite - wolf_opposite - 1;
if (tmp === 0) return 0;
wolf -= tmp;
wolf_opposite += tmp;
transport++;
}
}
return transport;
}
}