题目:一条小溪上7块石头,如图所示:

分别有六只青蛙:A,B,C,D,E,F。A,B,C三只蛙想去右岸,它们只会从左向右跳;D,E,F三只蛙想去左岸,它们只会从右向左跳。青蛙每次最多跳到自己前方第2块石头上。请问最少要跳几次所有青蛙上岸。写出步骤。

这个题是个路径搜索的问题,在解空间搜索所有的解,并找出最优的解法(即步骤最少的)。

那么怎么算是一个解呢?具体而言就是最后石头上没有青蛙了。

我们先给题目建模,7块石头,其上可以是没青蛙,可以有一只往左跳的青蛙,也可以有一只往右跳的青蛙。可以把这7块石头看成一个整体,来表示一个状态。这里我们把这7块石头看成一个数组,里面只能有0,1,2三种值,这样表示,那么初始时为:

1,1,1,0,2,2,2

我们把它再表示成一个数字,来表示状态值,这个值把这个数组按三进制拼成一个数字,我们用一个辅助函数来做这件事情:

private final int makeS() { int r=0; int p=1; for(int i=0;i<7;i++) { r+=p*states[i]; p*=3; } return r; }

那么题目现在变成从状态111022转换成状态0000000,所需最少的步骤.

那么状态是怎样转换的呢?

很显然。,每次青蛙跳都会触发状态的转换,我们在每个状态时搜索每种可能的转换,我们记初始状态为S(S等于三进制111022)记要求解的值为OPT(S),假如可以转换到t1,t2,...tk.

那么,显然

OPT(S)=min(1+OPT(t1),1+OPT(t2),....,1+OPT(tk));

另外,由于最终状态为0,所以OPT(0)=0,就是说已经在最终状态了,就不需要一步就可以了。

有了上面这个等式,我们可以递归求解了,但是如果单纯的递归,会导致大量的重复计算,所以这里我们用备忘录的方法,记下已经求解出来的OPT(x),放在一个数组里,由于只有7块石头,所以最多我们需要3^7=2187个状态。我们用一个2187个元素的数组,

其中第i个元素表示OPT(i),初始化每个元素用-1表示还未求解。OPT(0) 可直接初始化为0.

到此我们还有一个问题,怎么能够在算法结束的时候打印出最优的步骤呢?按照这个步骤,我们可以重建出青蛙是如何在最优的情况下过河的。为此,我们可以再用一个步骤数组,每次在采取最优步骤的时候记录下来。

整个算法如下:

package test; import java.util.Arrays; public class FrogJump { private int steps[]; private int states[]; private static class Step { int offset=-1; int jump; int jumpTo; } private Step jumps[]; private int initS; public FrogJump() { steps=new int[81*27]; states=new int[7]; for(int i=0;i<3;i++)states[i]=1; for(int i=4;i<7;i++)states[i]=2; Arrays.fill(steps, -1); steps[0]=0; jumps=new Step[81*27]; initS=makeS(); } public int shortestSteps(int s) { if(steps[s]==-1) { int minStep=Integer.MAX_VALUE; Step oneStep=new Step(); for(int i=0;i<7;i++) { if(states[i]==1) { if(i>4) { states[i]=0; minStep = recurFind(minStep,oneStep,i,7-i); states[i]=1; } else { if(states[i+1]==0) { states[i]=0; states[i+1]=1; minStep = recurFind(minStep,oneStep,i,1); states[i]=1; states[i+1]=0; } if(states[i+2]==0) { states[i]=0; states[i+2]=1; minStep = recurFind(minStep,oneStep,i,2); states[i]=1; states[i+2]=0; } } } else if(states[i]==2) { if(i<2) { states[i]=0; minStep = recurFind(minStep,oneStep,i,-1-i); states[i]=2; } else { if(states[i-1]==0) { states[i]=0; states[i-1]=2; minStep = recurFind(minStep,oneStep,i,-1); states[i]=2; states[i-1]=0; } if(states[i-2]==0) { states[i]=0; states[i-2]=2; minStep = recurFind(minStep,oneStep,i,-2); states[i]=2; states[i-2]=0; } } } } steps[s]=minStep; jumps[s]=oneStep; } return steps[s]; } private final int recurFind(int minStep, Step oneStep, int pos, int jump) { int toS=makeS(); int r=shortestSteps(toS); if(r { oneStep.jump=jump; oneStep.offset=pos; oneStep.jumpTo=toS; minStep=r+1; } return minStep; } public void printPath() { int s=initS; int i=1; while(s!=0) { System.out.println("["+(i++)+"] Frog at #"+jumps[s].offset+" jumps #"+jumps[s].jump); s=jumps[s].jumpTo; } } private final int makeS() { int r=0; int p=1; for(int i=0;i<7;i++) { r+=p*states[i]; p*=3; } return r; } public static void main(String[] args) { FrogJump fj=new FrogJump(); int steps=fj.shortestSteps(fj.initS); System.out.println("use "+steps+" steps!"); fj.printPath(); } }

运行结果:(#1表示向右跳一步,#-2表示向左跳二步。)

use 21 steps!

[1] Frog at #2 jumps #1 [2] Frog at #4 jumps #-2 [3] Frog at #5 jumps #-1 [4] Frog at #3 jumps #2 [5] Frog at #1 jumps #2 [6] Frog at #0 jumps #1 [7] Frog at #2 jumps #-2 [8] Frog at #0 jumps #-1 [9] Frog at #4 jumps #-2 [10] Frog at #2 jumps #-2 [11] Frog at #0 jumps #-1 [12] Frog at #5 jumps #2 [13] Frog at #3 jumps #2 [14] Frog at #1 jumps #2 [15] Frog at #5 jumps #2 [16] Frog at #3 jumps #2 [17] Frog at #5 jumps #2 [18] Frog at #6 jumps #-1 [19] Frog at #5 jumps #-2 [20] Frog at #3 jumps #-2 [21] Frog at #1 jumps #-2

老虎过河编程java_Java编程实例:青蛙过河程序及其解析相关推荐

  1. java青蛙过河打字_趣味算法——青蛙过河(JAVA)

    青蛙过河是一个非常有趣的智力游戏,其大意如下: 一条河之间有若干个石块间隔,有两队青蛙在过河,每队有3只青蛙,这些青蛙只能向前移动,不能向后移动,且一次只能有一只青蛙向前移动.在移动过程中,青蛙可以向 ...

  2. 计算器怎么编程java_java编程中怎样实现一个计算器

    展开全部 给你一个,前几天写e5a48de588b63231313335323631343130323136353331333264663637的 import java.awt.BorderLayo ...

  3. C/C++:Windows编程—IAT Hook实例(程序启动拦截)

    C/C++:Windows编程-IAT Hook实例(程序启动拦截) 前言+思路 本文默认读者有IAT Hook的相关的基础知识了哈,记录笔者在IAT Hook实战中遇到到问题以及解决思路. 笔者想实 ...

  4. 编程求解机械迷城第11关中类青蛙过河的问题

    在玩机械迷城游戏的时候,第11关遇到一个类似青蛙过河的游戏http://jingyan.baidu.com/article/e73e26c014903024adb6a7a4.html,下图是三张地图的 ...

  5. java游戏编程原理与实践教程_第18章青蛙过河游戏(Java游戏编程原理与实践教程课件).ppt...

    第18章 青蛙过河游戏 青蛙过河游戏是一个有趣的智力游戏.六只青蛙分成两队,左边三只,右边三只,都要过河,但是互不相让.中间只有一块空白石头.你需要用一种方法将左面的青蛙和右面的青蛙互换. 游戏说明: ...

  6. 青蛙爬井c语言编程,青蛙过河(ACM)

    青蛙过河(ACM) 青蛙过河 Time Limit:1000MS Memory Limit:32767K Total Submit:84 Accepted:51 Description 一条小溪尺寸不 ...

  7. 两个各四只青蛙过河java_Java实现 LeetCode 403 青蛙过河

    403. 青蛙过河 一只青蛙想要过河. 假定河流被等分为 x 个单元格,并且在每一个单元格内都有可能放有一石子(也有可能没有). 青蛙可以跳上石头,但是不可以跳入水中. 给定石子的位置列表(用单元格序 ...

  8. 算法-经典趣题-青蛙过河

    本文为joshua317原创文章,转载请注明:转载自joshua317博客 算法-经典趣题-青蛙过河 - joshua317的博客 一.问题 青蛙过河是一个非常有趣的智力游戏,其大意如下: 一条河之间 ...

  9. C语言青蛙过河游戏超详细教程【附源码】

    今天给大家带来一个青蛙过河小游戏代码,先看看效果吧! 开始界面: 游戏界面 : 游戏中界面:  胜利界面: 死亡界面: 代码我们分了几个模块来写,这样不容易写乱,也方便后续修改 木板模块: #incl ...

最新文章

  1. 过程控制系统模拟信号标准
  2. 数据结构--图(Graph)详解(一)
  3. 如何自动完成登录 SAP BTP workflow(工作流) 管理应用 Launchpad 所需的设置
  4. java object数组转实体类_详解Java中String JSONObject JSONArray List实体类转换
  5. dnf丢失clientbase_clientbase.dll
  6. 01.php面向对象
  7. IT项目管理之系统验收
  8. GNS3下载安装和使用、本地主机虚拟网卡消失解决方案以及环回网卡添加与测试
  9. docker安装微信
  10. 2路10核物理服务器能否虚拟40vcpu,XenServer中Windows 7与XP多vCPU支持配置,cpu 2 核限制...
  11. 使用igvtools可视化测序深度分布
  12. Mac应用程序无法打开或文件损坏的处理方法
  13. lua 5.3.5 TValue::tt_和GCObject::tt之间的爱恨纠葛
  14. Qiyuan-python接小球游戏
  15. 基于C#开发(WinForm)排队叫号系统【100010339】
  16. 数据库—行式存储和列式存储
  17. 界面设计方法 (1) — 1.界面的概念与分类
  18. 迷宫求解【穷举求解法】
  19. 如何安装SPSS软件
  20. maven出现lastupdated文件原因与分析

热门文章

  1. 浮点运算量FLOPs与算力单位FLOPS
  2. 2019 Android 高级面试题总结
  3. Https双向认证Android客户端配置
  4. 在使用ArcMap中的核密度分析时“输出像元大小”出现异常数的解决方案
  5. 程序员是干什么的呢?
  6. PPT资源记录---怕换电脑忘记这些东西,先行记录一波
  7. webpack配置排除打包
  8. 跟小甲鱼学Web开发笔记07
  9. 奥迪 a4 编码 控制计算机,大众/奥迪车电脑编码大全).doc
  10. PHP植发,《嫁给中也给他植发》c语言黑板擦_【衍生小说|言情小说】_晋江文学城...