【华为OD机试】羊、狼、农夫过河

羊、狼、农夫过河

问题描述

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

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

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

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

农夫自身不占用船的容量。

输入描述

第一行输入为M,N,X, 分别代表羊的数量,狼的数量,小船的容量。

输出描述

输出不损失羊情况下将全部羊和狼运到对岸需要的最小次数(若无法满足条件则输出0)。

示例

输入

5 3 3

输出

3

说明
第一次两只狼
第二次三只羊
第三次两只羊和一只狼

解题思路

需要渡河次数最小,则需要每次尽可能运输数量最大;

  • M + N < = X M + N <= X M+N<=X 时一次运输完成;
  • M < = X M <= X M<=X

N < M + X N < M + X N<M+X时:
1. 3 X > M + N > 2 X 3X > M + N > 2X 3X>M+N>2X,首次渡河时先运输M, 第二次运输狼数量M - 1, 第三次将剩余狼全部运输;
2. M + N < = 2 X M + N <= 2X M+N<=2X,首次满载运输狼,第二次所有运输;

N > = M + X N >= M + X N>=M+X时:
1. 首次全狼过河,岸边狼数量大于等于羊数量,羊被攻击;
2. 首次全羊过河,狼过河时必定需要拆分为两次,由于 N > = M + X N >= M + X N>=M+X,则至少需要输送M,对岸羊被攻击;

  • M > X M > X M>X

N > = M N >= M N>=M:首次运输存在两种情况, 狼比羊少(运输时岸边羊直接死亡)、全狼(第二次运输是为保证对岸羊比狼多, 岸边羊会少于狼数量)

N = M − 1 N = M - 1 N=M1:首次狼比羊少(岸边羊数量不大于狼), 全狼(第二次运输是为保证对岸羊比狼多, 岸边羊会不大于狼数量)

N < M − 1 N < M - 1 N<M1

N = M − 2 N = M - 2 N=M2

  1. 船容量为单数: M1 + N1 = X, M1 = N1 + 1, 后续Mi = Ni运输, 直至M1 + N1 <= X;
  2. 船容量为双数: M1 + N1 + 1 = X, 2M1 = X运输, 后续满负载M1 = N1运输

N < M − 2 N < M - 2 N<M2

  1. 船容量为单数, 先满容量运输 M1 = N1 + 1, 后续运输时先M1 = N1 + 1, 后M1 = N1 - 1满容量运行;
  2. 船容量为双数, 满容量运输 M1 = N1 + 2, 后续狼羊同等数量运输;

代码示例

/**
 * 狼羊过河最小过河次数
 * @param m 羊数量
 * @param n 狼数量
 * @param x 船容量
 * @return 最小过河次数
 */
public int wolfSheep(int m, int n, int x) {
    if((m + n) <= x) {
        return 1;
    }

    if(m <= x) {
        if(n >= x + m) {
            return 0;
        }

        return (m + n - 1) / x + 1;
    }

    if(n >= m - 1) {
        return 0;
    }

    if(n == m - 2) {
        if((x & 0b1) == 0) {
            return (m + n) / x + 1;
        } else {
            return (m + n - 3) / (x - 1) + 1;
        }
    }

    return (m + n - 1) / x + 1;
}
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值