牛客网. 龙与地下城游戏
题目概述
解题思路
这道题看上去要用动态规划处理。动归的一个关键在于构造最优子问题(也就是写递推公式)。对于这种矩阵形式的动态规划,另一个关键(也是我之前选择性忽略的)就是确定动态规划的方向(其实是在确立递推公式的初始的条件)。比方说,对于一个二维矩阵,我们究竟是从它的右下角往左上角递推,还是从它的左上角往右下角递推呢?对于很多题目来说,似乎两者都是OK的;但是在有些题目里(比如说这道题),可能选择就只有一种了。
对这题来说,我们首先要确定递推公式表示的内容是什么:我们维护一个二维数组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;
}
牛客网. 龙与地下城游戏相关推荐
- 牛客网 - 小乐乐打游戏(BFS)
链接:https://ac.nowcoder.com/acm/contest/301/G 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536 ...
- 牛客网获取输入rowinput_Python爬虫入门例题:抓取牛客网题目
最近做题的时候要写一些题解,在把牛客网的题目复制下来的时候,数学公式的处理比较麻烦,所以我用Python的selenium.urllib.request和BeautifulSoup4库对题目信息进行了 ...
- 使用Python网络爬虫抓取牛客网题目
文章目录 1. 背景 2. 前期准备 3. 获取网页内容 4. 内容处理 4.1. Limit 4.2. Problem Description 4.3. Input 4.4. Output 4.5. ...
- 牛客网:龙与地下城游戏
这题是走迷宫的升级版本吧. 我们反着从终点走到起点,设dp[i][j]代表从(i,j)走到终点的最少血量.mp表示迷宫里面的值. 我们要知道dp[i][j]和右边下边的mp,dp的关系. 思路如下: ...
- 牛客网 2018校招真题 美团点评 关灯游戏
Description 牛客网 2018校招真题 关灯游戏 Solving Ideas 只与最右边的数字有关,如果最右边的数字为1,则Alice赢,否则Bob赢 假设最右边的数字为1 因为Alice是 ...
- 牛客网 2018校招真题 网易 骰子游戏
Description 牛客网 2018校招真题 骰子游戏 Solving Ideas 参考<剑指offer>n个骰子的点数 考虑用两个数组来存储骰子点数的每一个总数出现的次数. 在一次循 ...
- 牛客网 2018年全国多校算法寒假训练营练习比赛(第三场)D.小牛vs小客-博弈
菜哭... D.小牛vs小客 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言65536K 64bit IO Format: %lld 链接:https://ww ...
- 牛客网 短最优升级路径 【Dijkstra算法】+【路径记录】
链接:https://www.nowcoder.com/questionTerminal/a7052c5bd8634edb9ccee711a5c1ea54 来源:牛客网 短最优升级路径 题目描述:游戏 ...
- 牛客网 New Game! 建图+最短路
链接:https://www.nowcoder.com/acm/contest/201/L 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 1048576K,其他语言20 ...
最新文章
- Tomcat服务器的常用配置
- 浅析网站结构如何开启优化工作
- 《电子商务法》实施倒计时,这些执行细则需注意!
- Mysql数据库的安装教程
- c++基础———循环结构
- linux安装apache下载文件,Linux安装apache详解
- 最细致的Spring Boot结合Vue前后端分离项目打包部署步骤(搭配Nginx)
- BZOJ5343 [Ctsc2018]混合果汁 【二分 + 主席树】
- Atitit 人脸识别 眼睛形态 attilax总结
- Chrome OS 初体验
- “IN-Chain全球区块链峰会”落幕 30余位大咖都说了什么
- npm/package.json/package-lock.json文件
- 《国史通鉴》- 宋朝
- 荣耀热键驱动无法安装
- 统计200~1000之间能被7整除数的个数。
- python三原色组合白色_为何色光三原色三三相加得到白色,这其中加色原理是如何起作用的?...
- Intel SGX开发者参考书(四)—— Enclave开发基础(三)
- 论文阅读:Softer-NMS: Rethinking Bounding Box Regression for Accurate Object Detection
- 矩阵的特性和运算法则
- solr4.4.0 集成 carrot2 支持中文和添加自己的中文分词器的方法。