题目概述

解题思路

这道题看上去要用动态规划处理。动归的一个关键在于构造最优子问题(也就是写递推公式)。对于这种矩阵形式的动态规划,另一个关键(也是我之前选择性忽略的)就是确定动态规划的方向(其实是在确立递推公式的初始的条件)。比方说,对于一个二维矩阵,我们究竟是从它的右下角往左上角递推,还是从它的左上角往右下角递推呢?对于很多题目来说,似乎两者都是OK的;但是在有些题目里(比如说这道题),可能选择就只有一种了。

图1. 动态规划求解的示意图

对这题来说,我们首先要确定递推公式表示的内容是什么:我们维护一个二维数组dp,数组的元素dp[i][j]表示从起始位置走到该处时,至少应具备多少的血量(也就是到这个地方的时候,最少应该有多少血)。那我们要求的值就是dp[0][0],也就是从起始位置出发的时候最少应该有多少血。我们的已知条件是:dp[M-1][N-1] = min(1, 1 - map[M-1][N-1])。这个已知条件是怎么来的呢?实际上,我们只需考虑两种情况:

  • 如果map[M-1][N-1]  < 0,也就是说到走到这个位置前,骑士血量至少是1-map[M-1][N-1];
  • 如果map[M-1][N-1] >= 0,那么骑士只要在map[M-1][N-2]或map[M-2][N-1]处达到最低血量的要求——1,走过来就没有问题了。

接下来,我们考虑如何构造递推公式。既然递推公式的初始值从右下角出发,而且dp[i][j]仅与它相邻的右/下两个元素相关,那么我们要做的工作还有两步:

  • 把dp[M-1][ J ]和dp[ I ][N-1]的值都算出来(0 <= J < N-1, 0 <= I < M-1),对应上图中紫色框的部分;
  • 构造关于dp[i][j]和dp[i][j+1]&dp[i+1][j]的递推式。

在做第二步的时候,我们可以先参考一下第一步的过程,看看能否抽象出它的步骤。求解的示意图如上图所示,我们从右下角绿勾位置出发,往左/上两个角度遍历求解。我们用题目给定的例子来推一下第一步的过程:

先考虑dp[0][2]~dp[2][2]和dp[2][0]~dp[2][2]的值该怎么取,下面给出求解过程。

map矩阵-2   -3   3
-5  -10   10   30  -5dp 矩阵?    ?   ??    ?   ??    ?   max(1, 1-(-5))?    ?   ??    ?   max(max(1, 1-1), 6-1)?    ?   6?    ?   max(max(1, 1-3), 5-3)?    ?   5?    ?   6?    ?   2?    ?   5?    max(1, 6-30)   6?    ?   ??    ?   ?max(1, 1-0)     1   6初始矩阵:?    ?   2?    ?   51    1   6

可以发现在矩阵的最下/右列,递推公式是:

  • dp[i][N-1] = max(1, dp[i+1][N-1] - map[i][N-1])
  • dp[M-1][j] = max(1, dp[M-1][j+1] - map[M-1][j])

推而广之即可得到:

由递推公式可知,这道题的空间复杂度是可以优化到O(min(M, N))的,因为它每次递推时,只需要用到上一层的信息。

方法性能

示例代码

#include<algorithm>
#include<iostream>
#include<math.h>
#include<queue>
#include<stdio.h>
#include<string.h>
#include<string>
#include<vector>
#define LEN 1000using namespace std;int A[LEN][LEN], dp[LEN][LEN], M, N;int main()
{scanf("%d%d", &M, &N);for (int i = 0; i < M; ++i)for (int j = 0; j < N; ++j)scanf("%d", &A[i][j]);dp[M - 1][N - 1] = max(1, 1 - A[M - 1][N - 1]);for (int j = N - 2; j >= 0; --j)dp[M - 1][j] = max(1, dp[M - 1][j + 1] - A[M - 1][j]);for (int i = M - 2; i >= 0; --i){dp[i][N - 1] = max(1, dp[i + 1][N - 1] - A[i][N - 1]);for (int j = N - 2; j >= 0; --j)dp[i][j] = min(max(1, dp[i + 1][j] - A[i][j]), max(1, dp[i][j + 1] - A[i][j]));}printf("%d", dp[0][0]);return 0;
}

牛客网. 龙与地下城游戏相关推荐

  1. 牛客网 - 小乐乐打游戏(BFS)

    链接:https://ac.nowcoder.com/acm/contest/301/G 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536 ...

  2. 牛客网获取输入rowinput_Python爬虫入门例题:抓取牛客网题目

    最近做题的时候要写一些题解,在把牛客网的题目复制下来的时候,数学公式的处理比较麻烦,所以我用Python的selenium.urllib.request和BeautifulSoup4库对题目信息进行了 ...

  3. 使用Python网络爬虫抓取牛客网题目

    文章目录 1. 背景 2. 前期准备 3. 获取网页内容 4. 内容处理 4.1. Limit 4.2. Problem Description 4.3. Input 4.4. Output 4.5. ...

  4. 牛客网:龙与地下城游戏

    这题是走迷宫的升级版本吧. 我们反着从终点走到起点,设dp[i][j]代表从(i,j)走到终点的最少血量.mp表示迷宫里面的值. 我们要知道dp[i][j]和右边下边的mp,dp的关系. 思路如下: ...

  5. 牛客网 2018校招真题 美团点评 关灯游戏

    Description 牛客网 2018校招真题 关灯游戏 Solving Ideas 只与最右边的数字有关,如果最右边的数字为1,则Alice赢,否则Bob赢 假设最右边的数字为1 因为Alice是 ...

  6. 牛客网 2018校招真题 网易 骰子游戏

    Description 牛客网 2018校招真题 骰子游戏 Solving Ideas 参考<剑指offer>n个骰子的点数 考虑用两个数组来存储骰子点数的每一个总数出现的次数. 在一次循 ...

  7. 牛客网 2018年全国多校算法寒假训练营练习比赛(第三场)D.小牛vs小客-博弈

    菜哭... D.小牛vs小客 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit IO Format: %lld 链接:https://ww ...

  8. 牛客网 短最优升级路径 【Dijkstra算法】+【路径记录】

    链接:https://www.nowcoder.com/questionTerminal/a7052c5bd8634edb9ccee711a5c1ea54 来源:牛客网 短最优升级路径 题目描述:游戏 ...

  9. 牛客网 New Game! 建图+最短路

    链接:https://www.nowcoder.com/acm/contest/201/L 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 1048576K,其他语言20 ...

最新文章

  1. Tomcat服务器的常用配置
  2. 浅析网站结构如何开启优化工作
  3. 《电子商务法》实施倒计时,这些执行细则需注意!
  4. Mysql数据库的安装教程
  5. c++基础———循环结构
  6. linux安装apache下载文件,Linux安装apache详解
  7. 最细致的Spring Boot结合Vue前后端分离项目打包部署步骤(搭配Nginx)
  8. BZOJ5343 [Ctsc2018]混合果汁 【二分 + 主席树】
  9. Atitit 人脸识别 眼睛形态 attilax总结
  10. Chrome OS 初体验
  11. “IN-Chain全球区块链峰会”落幕 30余位大咖都说了什么
  12. npm/package.json/package-lock.json文件
  13. 《国史通鉴》- 宋朝
  14. 荣耀热键驱动无法安装
  15. 统计200~1000之间能被7整除数的个数。
  16. python三原色组合白色_为何色光三原色三三相加得到白色,这其中加色原理是如何起作用的?...
  17. Intel SGX开发者参考书(四)—— Enclave开发基础(三)
  18. 论文阅读:Softer-NMS: Rethinking Bounding Box Regression for Accurate Object Detection
  19. 矩阵的特性和运算法则
  20. solr4.4.0 集成 carrot2 支持中文和添加自己的中文分词器的方法。

热门文章

  1. 微信公众号运营怎么做:这些小技巧,新手也可操作
  2. java 后端如何处理数据库字段类型为Json格式的方法
  3. 弘辽科技:微信下不动腾讯电商这盘棋
  4. 企业微信hook之实战开发
  5. itext生成PDF,天坑
  6. 华为手表GT3个个手机支持功能列表
  7. 用Python压缩和提取文件
  8. 15 openEuler使用DNF管理软件包
  9. Android将后台应用唤起到前台的方法
  10. 要是程序员都像他这样,何愁找不到女朋友