华为OD机试 羊狼过河问题 java版本

题目描述

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

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

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

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

输入描述

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

输出描述

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

用例1

输入

5 3 3

输出

3

说明

第一次运2只狼

第二次运3只羊

第三次运2只羊和1只狼

用例2

输入

5 4 1

输出

0

说明

如果找不到不损失羊的运送方案,输出0

 思路:这题我的思路是,定义一个过河函数,如下

在右边羊大于右边狼,或者右边没有羊的前提下:

正常的过河羊需要大于狼才可以,这种情况下,按照左边羊>狼+1,就送一只羊

左边羊=狼+1,而船余量>1,一只狼一只羊的送

左边羊=狼+1,而船余量=1,判断对岸羊>狼+1?,是就送一只狼

左侧无狼,就全送羊

这样保证了左侧羊>狼,右侧也尽可能让羊大于狼

但是这样还有特例

1.比如船可以一波把羊送走,狼<船余量*2-1,这样可以先送一船狼过去,然后左边羊>=狼+1,

再把剩余狼送过去,最后送羊,这种属于特例也要考虑进去

2.俩边都没有羊,只有狼,就只送狼就行了

函数如下:

public static int[] forriver(int sheep, int wolf, int boat,int sheep2, int wolf2){
        int[] arr = new int[5];//定义一个数组返回参数
        int boat2=boat;//定义一个船余量作为比较
        int jug=0;//定义一个运船成功与否判断
        while(boat2!=0&&jug==0){//
            jug=1;//开始定义判断为1,如果以下条件都没有达成,jug依然为1,跳出循环
            if(sheep>wolf+1&&(sheep2>wolf2||wolf2==0)){sheep--;boat2--;sheep2++;jug=0;}//羊大于狼+1,则运一只羊
            else if(sheep==wolf+1){//如果羊不大于狼+1,且还有狼和羊,对岸羊比狼多,则一只狼+一只羊的送
                if(boat2>1&&wolf!=0&&sheep!=0&&sheep2>wolf2){wolf--;sheep--;wolf2++;sheep2++;boat2-=2;jug=0;}
                //如果船余量没有俩个了,看看对岸的羊是否大于狼+1,并且还有狼,是就送一只狼
                if(boat2==1&&sheep2>wolf2+1&&wolf!=0){wolf--;wolf2++;boat2-=1;jug=0;}
            }//如果狼为0,就能送多少羊送多少羊
            if(wolf==0){while(boat2!=0&&sheep!=0){boat2--;sheep--;sheep2++;jug=0;}}
            if(sheep+wolf<boat2){sheep2+=sheep;wolf2+=wolf;sheep=0;wolf=0;boat2=0;}
            //如果狼和羊数量都少于余量,直接全部送走
            //特例,羊可以一波送走
            if(sheep2==0&&sheep<=boat&&wolf+wolf2<=boat*2-1&&wolf!=0){
                if(wolf2==0&&wolf>=boat2){wolf-=boat2;wolf2+=boat2;boat2=0;}
                else if(wolf2==boat2){wolf2+=wolf;wolf=0;boat2=0;}
                else if(wolf2==0){wolf2=wolf;boat2=0;wolf=0;}
            }//特例,没有羊只有狼
            if(sheep==0&&sheep2==0){while(boat2!=0&&wolf!=0){boat2--;wolf--;wolf2++;jug=0;}}
        }
        if(boat2==boat)arr[0]=1;//如果余量没有减少,则运送失败,数组第一个数改为1,意思是失败了
        else {arr[1]=sheep;arr[2]=wolf;arr[3]=sheep2;arr[4]=wolf2;}
        System.out.println("羊 狼 对岸羊 对岸狼:");
        System.out.println(sheep+" "+wolf+" "+sheep2+" "+wolf2);
        return arr;
    }
 

完整代码:

import java.util.Scanner;

public class Main {

    public static void main(String[] args){
        Scanner scanner = new Scanner(System.in);
        while(1==1) {
            System.out.println("输入羊数目 狼数目 船容量");
            int sheep = scanner.nextInt();//羊数目
            int wolf = scanner.nextInt();//狼数目
            int boat = scanner.nextInt();//船容量
            int sum = 0;//运送次数
            int sheep2 = 0;//对岸羊数目
            int wolf2 = 0;//对岸狼数目
            int[] array = new int[5];//定义一个数组接收函数返回的羊狼数目,以及是否达成运送条件
            while (sheep + wolf != 0) {
                array = forriver(sheep, wolf, boat, sheep2, wolf2);
                if (array[0] == 1) {
                    break;
                } else {
                    sheep = array[1];
                    wolf = array[2];
                    sheep2 = array[3];
                    wolf2 = array[4];
                    sum++;
                }
            }
            System.out.print("需要的次数为:");
            System.out.println(sum);
        }


    }
    public static int[] forriver(int sheep, int wolf, int boat,int sheep2, int wolf2){
        int[] arr = new int[5];//定义一个数组返回参数
        int boat2=boat;//定义一个船余量作为比较
        int jug=0;//定义一个运船成功与否判断
        while(boat2!=0&&jug==0){//
            jug=1;//开始定义判断为1,如果以下条件都没有达成,jug依然为1,跳出循环
            if(sheep>wolf+1&&(sheep2>wolf2||wolf2==0)){sheep--;boat2--;sheep2++;jug=0;}//羊大于狼+1,则运一只羊
            else if(sheep==wolf+1){//如果羊不大于狼+1,且还有狼和羊,对岸羊比狼多,则一只狼+一只羊的送
                if(boat2>1&&wolf!=0&&sheep!=0&&sheep2>wolf2){wolf--;sheep--;wolf2++;sheep2++;boat2-=2;jug=0;}
                //如果船余量没有俩个了,看看对岸的羊是否大于狼+1,并且还有狼,是就送一只狼
                if(boat2==1&&sheep2>wolf2+1&&wolf!=0){wolf--;wolf2++;boat2-=1;jug=0;}
            }//如果狼为0,就能送多少羊送多少羊
            if(wolf==0){while(boat2!=0&&sheep!=0){boat2--;sheep--;sheep2++;jug=0;}}
            if(sheep+wolf<boat2){sheep2+=sheep;wolf2+=wolf;sheep=0;wolf=0;boat2=0;}
            //如果狼和羊数量都少于余量,直接全部送走
            //特例,羊可以一波送走
            if(sheep2==0&&sheep<=boat&&wolf+wolf2<=boat*2-1&&wolf!=0){
                if(wolf2==0&&wolf>=boat2){wolf-=boat2;wolf2+=boat2;boat2=0;}
                else if(wolf2==boat2){wolf2+=wolf;wolf=0;boat2=0;}
                else if(wolf2==0){wolf2=wolf;boat2=0;wolf=0;}
            }//特例,没有羊只有狼
            if(sheep==0&&sheep2==0){while(boat2!=0&&wolf!=0){boat2--;wolf--;wolf2++;jug=0;}}
        }
        if(boat2==boat)arr[0]=1;//如果余量没有减少,则运送失败,数组第一个数改为1,意思是失败了
        else {arr[1]=sheep;arr[2]=wolf;arr[3]=sheep2;arr[4]=wolf2;}
        System.out.println("羊 狼 对岸羊 对岸狼:");
        System.out.println(sheep+" "+wolf+" "+sheep2+" "+wolf2);
        return arr;
    }

}

测试:

输入羊数目 狼数目 船容量
5 3 3
羊 狼 对岸羊 对岸狼:
3 2 2 1
羊 狼 对岸羊 对岸狼:
2 1 3 2
羊 狼 对岸羊 对岸狼:
0 0 5 3
需要的次数为:3
输入羊数目 狼数目 船容量
5 4 1
羊 狼 对岸羊 对岸狼:
5 4 0 0
需要的次数为:0
输入羊数目 狼数目 船容量
5 9 5
羊 狼 对岸羊 对岸狼:
5 4 0 5
羊 狼 对岸羊 对岸狼:
5 0 0 9
羊 狼 对岸羊 对岸狼:
0 0 5 9
需要的次数为:3
输入羊数目 狼数目 船容量
5 6 5
羊 狼 对岸羊 对岸狼:
5 1 0 5
羊 狼 对岸羊 对岸狼:
5 0 0 6
羊 狼 对岸羊 对岸狼:
0 0 5 6
需要的次数为:3
输入羊数目 狼数目 船容量
0 12 5
羊 狼 对岸羊 对岸狼:
0 7 0 5
羊 狼 对岸羊 对岸狼:
0 2 0 10
羊 狼 对岸羊 对岸狼:
0 0 0 12
需要的次数为:3
输入羊数目 狼数目 船容量
12 0 5
羊 狼 对岸羊 对岸狼:
7 0 5 0
羊 狼 对岸羊 对岸狼:
2 0 10 0
羊 狼 对岸羊 对岸狼:
0 0 12 0
需要的次数为:3
输入羊数目 狼数目 船容量
999 997 123
羊 狼 对岸羊 对岸狼:
937 936 62 61
羊 狼 对岸羊 对岸狼:
876 875 123 122
羊 狼 对岸羊 对岸狼:
815 814 184 183
羊 狼 对岸羊 对岸狼:
754 753 245 244
羊 狼 对岸羊 对岸狼:
693 692 306 305
羊 狼 对岸羊 对岸狼:
632 631 367 366
羊 狼 对岸羊 对岸狼:
571 570 428 427
羊 狼 对岸羊 对岸狼:
510 509 489 488
羊 狼 对岸羊 对岸狼:
449 448 550 549
羊 狼 对岸羊 对岸狼:
388 387 611 610
羊 狼 对岸羊 对岸狼:
327 326 672 671
羊 狼 对岸羊 对岸狼:
266 265 733 732
羊 狼 对岸羊 对岸狼:
205 204 794 793
羊 狼 对岸羊 对岸狼:
144 143 855 854
羊 狼 对岸羊 对岸狼:
83 82 916 915
羊 狼 对岸羊 对岸狼:
22 21 977 976
羊 狼 对岸羊 对岸狼:
0 0 999 997
需要的次数为:17
输入羊数目 狼数目 船容量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值