| 题引

相信大部分人童年都玩过大富豪这样一类的棋,棋格上面有加多少分,减多少分等等设置,比赛最终谁的分值最多(类似下面这个棋盘)


| 正题

设置小游戏为一个二维矩阵,
王子位于左上角,公主位于右下角,
每个单元格将会出现怪物或者补给

怪物:打斗减血(负数表示,且为整数)
补给:加血(正数表示,且为整数)

王子只能往下或者往右前进,
如果王子血量为0或负数,即为拯救失败,
求王子至少需要多少初始血量,才能抵达公主?

最优解: -2 — -3 — 3 — 1 — -5 需要初始血量为7


| 分析

先分析题目的重点:

  • 只能往右或着往下前进
  • 任意步只要血量掉0即失败(也就意味每步结束后血量至少保持1点)
  • 每步可能加血、减血,或者不变(为0时)

分析完重点,来看一些场景




看完3个小场景后,按常规思路,总结一个小规律
往下往右的时候,判断下和右的大小前进

那么这个结论是不是正确的呢,再来看下面一个场景…



按照上面总结的规律,得出这样的结论,如果细心的去计算的话,发现并不是最优解,虽然第一步的时候-3,但是+5之后,立马又回血了,正确的最优解如下:


至此,说明上面的小规律总结并不成立,那么就说明从正面打通思路就不行了,那么就逆向思维看看是否有解决办法?

再分析:
从后往前计算,计算当我达到这步的时候,应该需要多少血量(为了方便计算,我们计算每步的临界值,即到达这步血量为0,最终结果+1即可

以场景4为例:

计算到“王子”位置时,结果为2,表示王子位置出发,必须至少需要2+1=3血量

总结一下:

  • 逆向思维倒推,从后往前计算每步至少血量
  • 最右和最下边,可通过下面或后面的值,再与当前棋格的值计算可得出至少血量
  • 中间部分可通过相邻的右边和下边值判断出,再与当前棋格的值计算可得出至少血量

计算顺序逻辑图如下:


|编码

分析了这么多,我们按照分析思路去编码实现(小伙伴们可以自己先尝试编码看看

/*** @author yanghao* @version LeetCode174Test.java, v 0.1 2019-11-12 16:43*/
public class LeetCode174Test {public static void main(String[] args) {LeetCode174Test test = new LeetCode174Test();/*int[][] dungeon = new int[3][3];dungeon[0] = new int[]{-2, -3, 3};dungeon[1] = new int[]{-5, -10, 1};dungeon[2] = new int[]{10, 30, -5};*//*int[][] dungeon = new int[3][3];dungeon[0] = new int[]{1,-3,3};dungeon[1] = new int[]{0,-2,0};dungeon[2] = new int[]{-3,-3,-3};*/int[][] dungeon = new int[3][3];dungeon[0] = new int[]{1, -3, 5};dungeon[1] = new int[]{0, -5, 0};dungeon[2] = new int[]{-3, -3, 1};/*int[][] dungeon = new int[2][2];dungeon[0] = new int[]{2, 1};dungeon[1] = new int[]{1, -1};*//*int[][] dungeon = new int[2][2];dungeon[0] = new int[]{0, 5};dungeon[1] = new int[]{-2, -3};*//*int[][] dungeon = new int[2][1];dungeon[0] = new int[]{2};dungeon[1] = new int[]{1};*//*int[][] dungeon = new int[2][1];dungeon[0] = new int[]{1};dungeon[1] = new int[]{-1};*//*int[][] dungeon = new int[2][3];dungeon[0] = new int[]{3, -20, 30};dungeon[1] = new int[]{-3, 4, 0};*//*int[][] dungeon = new int[3][1];dungeon[0] = new int[]{1};dungeon[1] = new int[]{-2};dungeon[2] = new int[]{1};*//*int[][] dungeon = new int[1][2];dungeon[0] = new int[]{0, 0};*/System.out.println(test.leetCode174(dungeon));}public int leetCode174(int[][] dungeon) {int x = dungeon[0].length;int y = dungeon.length;if (dungeon == null || x == 0 || y == 0) {return 0;}//定义一个矩阵存储每格需要的血量,从后往前推算每格最少需要多少血量int[][] blood = new int[y][x];//填充最后一格blood[y - 1][x - 1] = Math.max(0, -dungeon[y - 1][x - 1]);//定义所需最少血量int lowBlood = 0;//填充最后一行for (int i = x - 2; i >= 0; i--) {lowBlood = blood[y - 1][i + 1] - dungeon[y - 1][i];blood[y - 1][i] = Math.max(0, lowBlood);}//填充最后一列for (int i = y - 2; i >= 0; i--) {lowBlood = blood[i + 1][x - 1] - dungeon[i][x - 1];blood[i][x - 1] = Math.max(0, lowBlood);}//填充中间部分for (int i = x - 2; i >= 0; i--) {for (int j = y - 2; j >= 0; j--) {lowBlood = Math.min(blood[j][i + 1], blood[j + 1][i]) - dungeon[j][i];blood[j][i] = Math.max(0, lowBlood);}}return blood[0][0] + 1;}}

|赠语

学习算法,思想很重要,要学会突破常规思路
(本题尝试了很多解决思路,这个算是比较优的解决办法,当然还可以通过其他方式去实现,小伙伴们尽情发挥自己的大脑吧,本题目来自LeetCode 174题,题目为了易懂,稍作精简改编)

“趣味”or“烧脑”算法 之 王子救公主相关推荐

  1. java王子救公主的游_计蒜客 王子救公主(DFS)

    一天,蒜头君梦见自己当上了王子,但是不幸的是,自己的公主被可恶的巫婆抓走了.于是蒜头君动用全国的力量得知,自己的公主被巫婆抓进一个迷宫里面.由于全国只有蒜头君自己可以翻越迷宫外的城墙,蒜头君便自己一人 ...

  2. DFS练习——王子救公主

    一天,蒜头君梦见自己当上了王子,但是不幸的是,自己的公主被可恶的巫婆抓走了.于是蒜头君动用全国的力量得知,自己的公主被巫婆抓进一个迷宫里面.由于全国只有蒜头君自己可以翻越迷宫外的城墙,蒜头君便自己一人 ...

  3. 计蒜客:王子救公主---dfs

    题目描述: 一天,蒜头君梦见自己当上了王子,但是不幸的是,自己的公主被可恶的巫婆抓走了.于是蒜头君动用全国的力量得知,自己的公主被巫婆抓进一个迷宫里面.由于全国只有蒜头君自己可以翻越迷宫外的城墙,蒜头 ...

  4. 【DFS题型九/双向DFS】王子救公主

    题目描述: 一天,蒜头君梦见自己当上了王子,但是不幸的是,自己的公主被可恶的巫婆抓走了.于是蒜头君动用全国的力量得知,自己的公主被巫婆抓进一个迷宫里面.由于全国只有蒜头君自己可以翻越迷宫外的城墙,蒜头 ...

  5. 计蒜客 王子救公主 dfs

    题意:如上,注意王子有可能跨越墙,前提使正好挨着墙. 思路:dfs王子和公主,开一个三维数组分别用vis[x][y][0],vis[x][y][1]标记王子和公主走到的点. 若存在二点相交即(vis[ ...

  6. 【深度优先搜索】计蒜客:王子救公主

    思路:用两次深度优先搜索,数组vis1标记王子可能到达的点,数组vis2标记公主可能到达的点: 如果两个数组有重复的标记的坐标,那么王子可以救出公主 !标记所有可能情况的深度优先搜索不需要回溯! 如果 ...

  7. 王子救公主 (计蒜客)一道简单DFS

    蓝桥杯不能粘贴  只能截图.. 这道题目很简单,主要想清楚 只要存在王子和公主都能到达的点,王子就能救出公主(此时必定有一个时刻可以让他们相遇) #include <bits/stdc++.h& ...

  8. 王子救公主(DFS)

    样例输入 1 8 w....#.g 样例输出 yes 解题思路: 两次搜索: 1.第一次对王子进行搜索,标记王子能到达的所有点. 2.第二次对公主进行搜索,如果公主能到达王子标记过的点,那么说明王子可 ...

  9. 【DFS专题训练】王子救公主 C++程序题

    题目描述 王子走两步,公主走一步,遇到#不能走,他们能否碰上 输入 1 8 w-#.g 输出 yes 思路 王子深搜一次记录走过的地方,公主深搜一次记录走过的地方,如果都走过就返回yes #inclu ...

最新文章

  1. 《iOS 6核心开发手册(第4版)》——2.1节UIControl类
  2. 樱桃键盘驱动在哪下_手感还是信仰?樱桃Cherry MX8.0与MC 8.1军火箱键鼠套装体验点评...
  3. 东南大学王萌 | “神经+符号”学习与多模态知识发现
  4. 利用国内镜像加快pip下载速度和成功率
  5. OPTIRRA研究: TNF拮抗剂维持期优化减量方案[EULAR2015_SAT0150]
  6. 分解原理_葛兰维均线的数学拟合原理--傅立叶函数的分解的应用
  7. 一个程序员的书法学习之路-法帖篇
  8. Git 64位安装包下载
  9. java号码池_Java常量池详解
  10. 收银机多少钱一台推荐科脉系统_收银系统多少钱一套?常用收银系统价格大盘点...
  11. 维生素D与肠道菌群的互作
  12. 两个服务器微信消息模板发不出去,小程序模板消息调用send大部分情况下发送不出去,但有时又可以发送,什么情况?...
  13. 用Python做一个久坐提醒小助手
  14. c# NPOI 导出Excel 冻结窗格
  15. 九爷带你了解 Tomcat 优化
  16. matlab下载光盘刻录,最新的linux下dvd刻录软件,支持DVD+RW、DVD-RW光盘刻录。
  17. Java打印乘法口诀表(任何数)
  18. html加载背景图片
  19. 关于25Qxx踩坑总结(无法写入)
  20. “以简驭繁”打造卓越校园网 ——锐捷助力西安理工大学校园网建设

热门文章

  1. C++ malloc、智能指针、类型转换等(三)
  2. GlusterFS 配置及使用 二 :Windows挂载GlusterFS
  3. 加州大学圣塔芭芭拉分校计算机排名,加州大学圣塔芭芭拉分校世界排名及专业排名汇总(QS世界大学排名版)...
  4. 分治法典型体现之快速排序(一遍单项扫描)
  5. 厉害了:杀毒软件卡巴斯基将推出二次元萌妹形象,C92见
  6. MySQL数据库基本操作---DDL
  7. 单相电机正反转接线图_单相电机正反转接线图
  8. 【PaperReading】情感人的互联网:通过视听信号实现跨文化的可持续情感计算
  9. 免费提供一个完整股票分析软件源码(包含开发文档)
  10. 终结者2进去后显示天网服务器,《终结者2:审判日》天网觉醒秘测开服公告