1. 程式人生 > 其它 >演算法-經典趣題-青蛙過河

演算法-經典趣題-青蛙過河

一、問題

青蛙過河是一個非常有趣的智力遊戲,其大意如下:

一條河之間有若干石塊間隔,有兩隊青蛙在過河,每隊有3只青蛙,如圖所示。這些青蛙只能向前移動,不能向後移動,且一次只能有一隻青蛙向前移動。在移動過程中,青蛙可以向前面的空位中移動,不可一次跳過兩個位置,但是可以跳過對方一隻青蛙進入前面的一個空位。問兩隊青蛙該如何移動才能夠用最少的步數分別走向對岸?

二、分析

我們來分析一下青蛙過河問題。可以採用如下方案來移動青蛙,操作步驟如下:

(1)左側的青蛙向右跳過右側的一隻青蛙,落入空位,執行第(5)步。

(2)右側的青蛙向左跳過左側的一隻青蛙,落入空位,執行第(5)步。

(3)左側的青蛙向右移動一格,落入空位,執行第(5)步。

(4)右側的青蛙向左移動一格,落入空位,執行第(5)步。

(5)判斷是否已將兩隊青蛙移到對岸,如果沒有則繼續從第(1)步執行,否則結束程式。

三、程式設計

package com.joshua317;

import jdk.nashorn.internal.ir.LiteralNode;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        FrogCrossRiver frogCrossRiver = new FrogCrossRiver();
        List frogQueue = frogCrossRiver.initFrogQueue();

        String frogJumpInfo = (frogCrossRiver.frogJump(frogQueue, 3));
        System.out.println("青蛙跳躍的順序為:\r\n " + frogJumpInfo);
    }
}

class Frog {
    static enum frogDirection {向左, 向右};
    public String frogName;//青蛙名稱
    public int position;//青蛙位置
    public frogDirection direction;//青蛙跳動的方向
    public boolean canJump;//是否可以跳
    public boolean isEmpty = false;//是否是空格

    //建構函式
    public Frog (int position, String frogName, frogDirection direction, boolean canJump) {
        this.position = position;
        this.frogName = frogName;
        this.direction = direction;
        this.canJump = canJump;
    }

    public Frog (int position) {
        this.frogName = "空";
        this.position = position;
        this.canJump = false;
        this.isEmpty = true;
    }
    public Frog (Frog frog) {
        this.position = frog.position;
        this.frogName = frog.frogName;
        this.direction = frog.direction;
        this.canJump = frog.canJump;
        this.isEmpty = frog.isEmpty;
    }

}

class FrogCrossRiver {
    //初始化青蛙佇列
    public List<Frog> initFrogQueue()
    {
        List<Frog> frogQueue = new ArrayList<Frog>();
        frogQueue.add(new Frog(0, "左1", Frog.frogDirection.向右, false));
        frogQueue.add(new Frog(1, "左2", Frog.frogDirection.向右, true));
        frogQueue.add(new Frog(2, "左3", Frog.frogDirection.向右, true));
        frogQueue.add(new Frog(3));

        frogQueue.add(new Frog(4, "右1", Frog.frogDirection.向左, true));
        frogQueue.add(new Frog(5, "右2", Frog.frogDirection.向左, true));
        frogQueue.add(new Frog(6, "右3", Frog.frogDirection.向左, false));

        return frogQueue;
    }

    //當一個青蛙跳動後,形成一個新的佇列
    private List<Frog> editFrogQueue(List<Frog> frogQueue, String frogName, int oldEmptyPostionId, int newEmptyPostionId)
    {
        List<Frog> newFrogQueue = new ArrayList<Frog>();
        for (int i=0; i<frogQueue.size(); i++) {
            Frog frog = (Frog)frogQueue.get(i);
            Frog newFrog = new Frog(frog);
            if (newFrog.isEmpty) {
                newFrog.position = newEmptyPostionId;
            }
            if (newFrog.frogName == frogName) {
                newFrog.position = oldEmptyPostionId;
            }
            newFrog.canJump = false;
            if ((newEmptyPostionId - newFrog.position) > 0 &&
                    (newEmptyPostionId - newFrog.position) < 3 &&
                    newFrog.direction == Frog.frogDirection.向右) {
                newFrog.canJump = true;
            }

            if ((newFrog.position - newEmptyPostionId) > 0 &&
                    (newFrog.position - newEmptyPostionId) < 3 &&
                    newFrog.direction == Frog.frogDirection.向左) {
                newFrog.canJump = true;
            }
            newFrogQueue.add(newFrog);
        }
        return newFrogQueue;
    }

    //是否已經完成位置對換,即前三個青蛙的位置都大於3
    private boolean isComplete(List<Frog> frogQueue)
    {
        return (frogQueue.get(0).position > 3 && frogQueue.get(1).position > 3 && frogQueue.get(2).position > 3);
    }

    //是否還有可以跳動的青蛙,只有可以跳動的,就沒有達到最後的狀態,
    //但都不可以跳動了也不一定對換完了,這裡只是控制遞迴
    private boolean canFrogJump(List<Frog> frogQueue)
    {
        for (int i=0; i<frogQueue.size(); i++) {
            Frog frog = (Frog)frogQueue.get(i);
            if (frog.canJump) {
                return true;
            }
        }
        return false;
    }

    //獲取青蛙跳動的步驟
    public String frogJump(List<Frog> frogQueue, int emptyPositionId)
    {
        String frogJumpInfo = "";
        for (int i=0; i<frogQueue.size(); i++) {
            Frog frog = (Frog)frogQueue.get(i);
            //是空位置
            if (frog.isEmpty) {
                continue;
            }
            //不能跳
            if (!frog.canJump) {
                continue;
            }
            frogJumpInfo = "青蛙" + frog.frogName + " " + frog.direction + "跳到第" + (emptyPositionId + 1) + "個位置" +
                    "\r\n";
            int newPositionId = frog.position;
            List<Frog> newFrogQueue = this.editFrogQueue(frogQueue, frog.frogName, emptyPositionId,newPositionId);

            //只要能繼續跳就遞迴
            if (this.canFrogJump(newFrogQueue)) {
                frogJumpInfo += this.frogJump(newFrogQueue, newPositionId);
            } else {
                if (this.isComplete(newFrogQueue)) {
                    frogJumpInfo += "成功";
                    break;
                }
            }
            if (frogJumpInfo.contains("成功")) {
                break;
            }
        }
        return frogJumpInfo;
    }
}

四、練習

大家可以想一想如果是4只青蛙,5只青蛙,6只青蛙呢?

附一個小遊戲的連結:http://www.4399.com/flash/204168_4.htm