华为OD-农夫狼羊过河问题

题目描述:一个农夫带着m只羊,n只狼过河,农夫有一条可载x只羊/狼的船,农夫在时或者羊的数量大于狼时,狼不会攻击羊;农夫在不损失羊的情况下,运输几次可以完成运输?

备注:羊和狼只会被运送一次,返程不会携带。

输入描述: 输入参数为m,n,x; m为羊的数量,n为狼的数量,x为船的承载量

 输出描述: 输出最少完成运输的次数,如无法在不损失羊的情况下完成运输,则返回-1

示例: 

输入: 5 3 3

输出: 3

说明:详解:

第一次:2只狼

第二次:3只羊

第三次:2只羊,1只狼

思路:每次携带羊狼过河后,只要河岸两边羊的数量大于狼,或者只有一种动物,羊都不会损失,因此每次携带羊狼时候,我们需要保证确保该次携带是可行的,而且尽可能多带,这样运输次数才会最少,递归调用携带方法,直到所用狼和羊均运送完成。

用四个变量m,n,m1,n1分别记当前剩余羊的数量,狼的数量,以及对岸羊和狼的数量,用i和j分别记住每次携带羊和狼的数量。

 public static int ship(int m, int n, int x, int m1, int n1, int count) {
        if ((m + n) <= x) {
            System.out.println("第" + (count + 1) + "次运送, " + (m) + " : " + (0));
            return count + 1;
        } else if ((m <= x) && (n <= x)) {
            System.out.println("第" + (count + 1) + "次运送, " + (m) + " : " + (0));
            System.out.println("第" + (count + 2) + "次运送, " + (0) + " : " + (n));
            return count + 2;
        } else if ((count == 0) && ((m - n) < 2)) {
            //如果羊最多比狼多一只,则无法完成运送
            return -1;
        }
        //每次尽量多携带
        for (int onceCount = x; onceCount > 0; onceCount--) {
            for (int i = onceCount; i >= 0; i--) {
                //本次运送的量,大于实际的量,则跳过
                if ((i > m) || ((onceCount - i) > n)) {
                    continue;
                }
                //确保本次运送后,羊的数量大于狼,若状态正确,则即可运输
                int m2 = m - i;
                int n2 = n - (onceCount - i);
                int m3 = m1 + i;
                int n3 = n1 + (onceCount - i);
                if (((m2 > n2) || (m2 == 0) || (n2 == 0)) && ((m3 > n3) || (m3 == 0) || (n3 == 0))) {
                    System.out.println("第" + (count + 1) + "次运送, " + (i) + " : " + (onceCount - i));
                    //递归运送,若返回结果大于0,则表面该运送策略可行
                    int ship = ship(m2, n2, x, m3, n3, count + 1);
                    if (ship > 0) {
                        return ship;
                    }
                }
            }
        }
        return -1;
    }

测试运行:

public class Test {

    public static void main(String[] args) {
        System.out.println("总运输次数:" + ship(5, 3, 3, 0, 0, 0));
    }

}

运行结果:

第1次运送, 2 : 1
第2次运送, 3 : 0
第3次运送, 0 : 2
总运输次数:3

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值