华为机试 - 羊、狼、农夫过河
创始人
2024-03-14 09:26:49
0

目录

题目描述

输入描述

输出描述

用例

题目解析

算法源码


题目描述

羊、狼、农夫都在岸边,当羊的数量小于狼的数量时,狼会攻击羊,农夫则会损失羊。农夫有一艘容量固定的船,能够承载固定数量的动物。

要求求出不损失羊情况下将全部羊和狼运到对岸需要的最小次数。

只计算农夫去对岸的次数,回程时农夫不会运送羊和狼。

备注:农夫在或农夫离开后羊的数量大于狼的数量时狼不会攻击羊。

输入描述

第一行输入为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;}
}

相关内容

热门资讯

汽车油箱结构是什么(汽车油箱结... 本篇文章极速百科给大家谈谈汽车油箱结构是什么,以及汽车油箱结构原理图解对应的知识点,希望对各位有所帮...
美国2年期国债收益率上涨15个... 原标题:美国2年期国债收益率上涨15个基点 美国2年期国债收益率上涨15个基...
嵌入式 ADC使用手册完整版 ... 嵌入式 ADC使用手册完整版 (188977万字)💜&#...
重大消息战皇大厅开挂是真的吗... 您好:战皇大厅这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...
盘点十款牵手跑胡子为什么一直... 您好:牵手跑胡子这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游...
senator香烟多少一盒(s... 今天给各位分享senator香烟多少一盒的知识,其中也会对sevebstars香烟进行解释,如果能碰...
终于懂了新荣耀斗牛真的有挂吗... 您好:新荣耀斗牛这款游戏可以开挂,确实是有挂的,需要了解加客服微信8435338】很多玩家在这款游戏...
盘点十款明星麻将到底有没有挂... 您好:明星麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【5848499】很多玩家在这款游戏...
总结文章“新道游棋牌有透视挂吗... 您好:新道游棋牌这款游戏可以开挂,确实是有挂的,需要了解加客服微信【7682267】很多玩家在这款游...
终于懂了手机麻将到底有没有挂... 您好:手机麻将这款游戏可以开挂,确实是有挂的,需要了解加客服微信【8435338】很多玩家在这款游戏...