【動態規劃:路徑問題】最小路徑和 地下城游戲

在這里插入圖片描述

最小路徑和(medium)

64. 最小路徑和

? 給定一個包含非負整數的 m x n 網格 grid ,請找出一條從左上角到右下角的路徑,使得路徑上的數字總和為最小。

? **說明:**每次只能向下或者向右移動一步。

示例 1:

在這里插入圖片描述

輸入:grid = [[1,3,1],[1,5,1],[4,2,1]]
輸出:7
解釋:因為路徑 1→3→1→1→1 的總和最小。

示例 2:

輸入:grid = [[1,2,3],[4,5,6]]
輸出:12

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 200
  • 0 <= grid[i][j] <= 100

解題思路

? 首先還是狀態表示,依照路徑問題的經驗和題目要求,可以很容易的設定 dp[i][j] 表示到達 [i, j] 位置時的最小路徑和

? 接著就是狀態轉移方程,根據最近一步來推導的話,和 [i, j] 有關系的就是 [i-1, j][i, j-1] 這兩格了,以前者為例,dp[i-1][j] 表示到達 [i-1, j] 位置時候的最小路徑和,那么 dp[i, j] 想得到最小路徑和,不就是 [i-1, j] 的最小路徑和,加上 [i, j] 當前的大小 嗎,很簡單明了,對于 [i, j-1] 也同樣如此!

? 既然要的是最小的路徑和,我們只需要取 dp[i-1][j]dp[i][j-1] 中小的那個加上當前的大小即可!

? 所以狀態轉移方程為:dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i][j]

? 然后還是初始化問題,因為我們要給表格加上虛擬行列,并且因為我們的狀態轉移方程是根據左邊和上邊格子得到的,這樣子的話我們只需要多加一行一列,放在最上邊和最左邊這一行一列作為虛擬行列!

? 現在考慮兩個問題,①虛擬行列的初始值不能影響后面填表的正確;②下標的映射關系。

? 其實最重要的還是第一個,因為我們在左上角開始遍歷,需要讓 dp[1][1] 得到的還是原來 gird 中的值,所以 得讓 dp[0][1] 或者 dp[1][0] 為 0,保證加的時候加 0,就不會有影響了,而 其它位置都設為 INT_MAX,因為其它邊界位置其實是不想收到這個虛擬行列的影響的,只希望收到附近的非虛擬位置的影響,所以用 INT_MAX 的時候進行最小值判斷就不會取到它了!

在這里插入圖片描述

? 填表順序就是從上往下,從左往右

? 最后返回的就是右下角的值也就是到達右下角的最小路徑和!

class Solution {
public:int minPathSum(vector<vector<int>>& grid) {int m = grid.size();int n = grid[0].size();vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT_MAX)); // 多開一行一列給虛擬行列,都設為INT_MAXdp[0][1] = 0; // 初始化虛擬位置for(int i = 1; i <= m; ++i){for(int j = 1; j <= n; ++j){dp[i][j] = min(dp[i-1][j], dp[i][j-1]) + grid[i-1][j-1];}}return dp[m][n];}
};

地下城游戲(hard)

174. 地下城游戲

? 惡魔們抓住了公主并將她關在了地下城 dungeon右下角 。地下城是由 m x n 個房間組成的二維網格。我們英勇的騎士最初被安置在 左上角 的房間里,他必須穿過地下城并通過對抗惡魔來拯救公主。

? 騎士的初始健康點數為一個正整數。如果他的健康點數在某一時刻降至 0 或以下,他會立即死亡。

? 有些房間由惡魔守衛,因此騎士在進入這些房間時會失去健康點數(若房間里的值為負整數,則表示騎士將損失健康點數);其他房間要么是空的(房間里的值為 0),要么包含增加騎士健康點數的魔法球(若房間里的值為正整數,則表示騎士將增加健康點數)。

? 為了盡快解救公主,騎士決定每次只 向右向下 移動一步。

? 返回確保騎士能夠拯救到公主所需的最低初始健康點數。

**注意:**任何房間都可能對騎士的健康點數造成威脅,也可能增加騎士的健康點數,包括騎士進入的左上角房間以及公主被監禁的右下角房間。

示例 1:
在這里插入圖片描述

輸入:dungeon = [[-2,-3,3],[-5,-10,1],[10,30,-5]]
輸出:7
解釋:如果騎士遵循最佳路徑:右 -> 右 -> 下 -> 下 ,則騎士的初始健康點數至少為 7 。

示例 2:

輸入:dungeon = [[0]]
輸出:1

提示:

  • m == dungeon.length
  • n == dungeon[i].length
  • 1 <= m, n <= 200
  • -1000 <= dungeon[i][j] <= 1000

解題思路

? 這道題乍一看和上面幾道路徑題好像差不多,但其實這道題隱藏很多細節,稍不注意就出錯,至少我是這樣子的!為什么這么說呢???

? 按我們上面做題的經驗來看,我們都是以 [i, j] 為結尾怎么這么樣這種情況,但是在這道題中,這種狀態表示其實是不正確的,是推導不出來的,我們來舉個例子:

在這里插入圖片描述

? 注意:上圖中的例子只是為了表達這種狀態表示是錯誤的,其實例子的一些細節是錯誤的,注意即可!

? 所以我們就得改變一下思考方式,考慮從后面往前推導,也就是說以 [i, j] 為起點怎么怎么樣這種情況,其實通過后面講解會看到這樣子是行得通的!

? 所以我們的狀態表示 dp[i][j] 表示以 [i, j] 為起點,到達終點也就是右下角的最低健康點數

? 也就是說現在我們推導的就是 dp[0][0] 了,那么就得 從后往前推導

?

? 接著就是狀態轉移方程,既然是從后往前推導,那么肯定是和當前格子的右邊或者下邊有關系。解釋如下圖:

在這里插入圖片描述

? 除此之外,上圖中還解釋了初始化的問題,并且我們并不需要去關心下標映射的問題,因為我們的虛擬行列是開在最后一行和最后一列!

? 填表的順序的話,就是從下往上,每行從右往左

? 返回值就是左上角的值!

?

這樣子就結束了嗎???

? 結束就錯了,還有一個細節我們沒有處理!仔細想一下上面的狀態轉移方程,其中是涉及到了減法,要是遇到一種情況,就是 dungeon[i][j] 是一個正數,也就相當于這道題的一個加血點,如果它很大,導致減完之后得到的是一個負數,那么 dp[i][j] 是一個負數肯定是錯誤的啊,它表示的是最小健康點數,小于等于 0 不就掛了嗎對不對!

? 所以我們必須處理一下,為了讓其減去一個很大的負數之后還能得到一個最小的健康點數,我們想到的就是 1,所以我們在執行完狀態轉移方程之后還必須做一次判斷,或者直接處理這個數,使得 dp[i][j] 不會成為一個負數,如果是負數了,就讓它變成最小的健康點數 1 即可,代碼如下:

dp[i][j] = max(1, dp[i][j]);

class Solution {
public:int calculateMinimumHP(vector<vector<int>>& dungeon) {int m = dungeon.size();int n = dungeon[0].size();vector<vector<int>> dp(m + 1, vector<int>(n + 1, INT_MAX)); // 加入虛擬行列dp[m][n-1] = 1; // 將右下角的最近一步初始化為1,這樣子的話保證了初始健康點數的q'z// 從下往上,從右往左填表for(int i = m-1; i >= 0; --i){for(int j = n-1; j >= 0; --j){dp[i][j] = min(dp[i+1][j], dp[i][j+1]) - dungeon[i][j];dp[i][j] = max(1, dp[i][j]); // 細節,不能遺漏}}return dp[0][0];}
};

在這里插入圖片描述

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/93798.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/93798.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/93798.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SQL詳細語法教程(七)核心優化

以下對 SQL 優化 涉及的關鍵場景&#xff08;含 update 行鎖優化&#xff09;進行極致詳細的拆解&#xff0c;從底層原理、執行流程到實戰代碼、避坑指南全維度覆蓋&#xff0c;搭配表格對比讓邏輯更清晰&#xff1a;一、SQL 優化 - COUNT 優化1. 底層原理&#xff1a;COUNT() …

Tomcat 的核心腳本catalina.sh 和 startup.sh的關系

catalina.sh 和 startup.sh 都是 Tomcat 的核心腳本&#xff0c;但它們的角色和使用場景有所不同。以下是它們的主要區別和適用場景&#xff1a;1. 功能區別腳本主要用途底層調用關系startup.sh一個快捷入口腳本&#xff0c;用于快速啟動 Tomcat&#xff08;后臺模式&#xff0…

飛算JavaAI:簡易貪吃蛇小游戲

目錄先確定核心功能技術選型核心功能實現過程1. 數據模型設計2. 游戲界面和繪制邏輯3. 游戲主框架和事件處理飛算JavaAI在開發中的應用體驗可以進一步優化的地方作為Java課程的小作業&#xff0c;不想做太復雜的管理系統&#xff0c;就選了貪吃蛇這個經典小游戲。全程用Swing做…

如何保障內部網絡安全前提下,實現與外部互聯網之間的文件傳輸?

在數字化時代&#xff0c;企業網絡環境日益復雜&#xff0c;普遍采用“內外網隔離”的安全架構&#xff1a;內部辦公網承載業務系統與數據&#xff0c;外部互聯網則用于對外溝通與信息獲取。這種隔離有效抵御了外部攻擊&#xff0c;但也帶來了“信息孤島”問題——如何在保障內…

計算機視覺 圖片處理 在骨架化過程中,每次迭代都會從圖像的邊緣移除一層像素,直到只剩下單像素寬度的骨架

你說得對&#xff0c;if cv2.countNonZero(binary) 0: break 這個條件確實表示圖像中已經沒有非零像素&#xff0c;即圖像完全變為空白。這并不是骨架化完成的標志&#xff0c;而是表示圖像已經被腐蝕到沒有任何內容了。 在骨架化過程中&#xff0c;我們需要一個更合適的停止條…

rt-thread audio框架移植stm32 adc+dac,用wavplayer錄音和播放

D1 參考 rt-thread官方sdk中&#xff0c;正點原子stm32f429-atk-appollo的board中有audio文件夾&#xff0c;包括了mic/play的程序&#xff0c;wm8978的庫文件因為我們基于stm32h750內置adcdac設計&#xff0c;所以不需要wm8978.c/h。只需要移植drv_sound.c和drv_mic.c D2 工程…

AI重塑軟件測試:質量保障的下一站

軟件開發的世界變化飛快&#xff0c;系統越來越復雜&#xff0c;用戶的胃口越來越大&#xff0c;產品上線的壓力也越來越大。作為測試工程師&#xff0c;你是不是常常覺得傳統測試已經跟不上節奏了&#xff1f;手工測試累死人&#xff0c;自動化腳本維護到崩潰&#xff0c;測試…

【前端基礎知識系列六】React 項目基本框架及常見文件夾作用總結(圖文版)

在 React 開發中&#xff0c;一個清晰合理的項目結構不僅能提高開發效率&#xff0c;還能讓代碼更易于維護和擴展。尤其是在團隊協作中&#xff0c;統一的項目結構規范至關重要。本文將通過圖文結合的方式&#xff0c;詳細介紹 React 項目的基本框架以及常見文件夾的定義與作用…

0815 UDP通信協議TCP并發服務器

Part 1.思維導圖一.UDP通信協議1.原理服務器端&#xff1a;1.用socket函數創建一個套接字文件2.創建服務器端地址結構體并賦值3.用ford函數將套接字文件與地址結構體綁定4.創建接收客戶端地址結構體5.利用sendto和recvfrom函數傳輸和接收信息客戶端&#xff1a;1.用socket函數創…

一個基于純前端技術實現的五子棋游戲,無需后端服務,直接在瀏覽器中運行。

一 功能特性1.1 核心游戲功能- **標準五子棋規則**&#xff1a;1515棋盤&#xff0c;黑子(玩家)先手 - **AI對戰模式**&#xff1a;白子AI具有中等難度&#xff0c;會進行智能進攻和防守 - **勝負判定**&#xff1a;支持橫向、縱向、斜向五子連線獲勝 - **平局檢測**&#xff1…

HBuilderX升級,Vue2 scss 預編譯器默認已由 node-sass 更換為 dart-sass

目錄 一、問題描述 二、問題原因 三、問題解析及解決方案 一、問題描述 最近開發新項目&#xff0c;升級了HBuilderX版本到4.75&#xff0c;最近要在之前的項目添加功能的時候發現報錯&#xff0c;錯誤如下&#xff1a;Vue2 scss 預編譯器默認已由 node-sass 更換為 dart-sa…

像素風球球大作戰 HTML 游戲

像素風球球大作戰 HTML 游戲 下面是一個簡單的像素風格球球大作戰 HTML 游戲代碼&#xff1a; <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-widt…

文件導出時無法獲取響應頭Content-Disposition的文件名

1. 為什么Content-Disposition無法獲取&#xff1f; 要拿到 Content-Disposition 里的 filename&#xff0c;可以用正則或者簡單的字符串解析。 瀏覽器默認不讓前端訪問非標準響應頭&#xff0c;Content-Disposition 需要后端顯式暴露。 在瀏覽器開發者工具 → Network → Re…

Leetcode 128. 最長連續序列 哈希

原題鏈接&#xff1a; Leetcode 128. 最長連續序列 解法1: map&#xff0c;不符合要求 class Solution { public:int longestConsecutive(vector<int>& nums) {if (nums.size()0) return 0;map<int,int> mp;for(auto x: nums){mp[x];}int pre;int l0,r0,res0;…

禾賽激光雷達AT128P/海康相機(2):基于歐幾里德聚類的激光雷達障礙物檢測

目錄 一、參考連接 二、實驗效果?編輯 三、安裝相應的 ros 依賴包 四、代碼驅動 4.1 代碼下載 4.2 代碼文件放置(請按照這個命名放置代碼) 4.3 代碼編譯 4.4 報錯 一、參考連接

Vue Router的常用API有哪些?

文章目錄一、路由配置相關二、路由實例方法&#xff08;router 實例&#xff09;三、組件內路由 API&#xff08;useRouter / useRoute&#xff09;四、導航守衛&#xff08;路由攔截&#xff09;五、路由視圖與導航組件六、其他常用 API七、history模式和hash模式有什么區別&a…

從現場到云端的“通用語”:Kepware 在工業互聯中的角色、使用方法與本土廠商(以胡工科技為例)的差異與優勢

從現場到云端的“通用語”&#xff1a;Kepware 在工業互聯中的角色、使用方法與本土廠商&#xff08;以胡工科技為例&#xff09;的差異與優勢 文章目錄從現場到云端的“通用語”&#xff1a;Kepware 在工業互聯中的角色、使用方法與本土廠商&#xff08;以胡工科技為例&#x…

深入理解Prompt構建與工程技巧:API高效實踐指南

深入理解Prompt構建與工程技巧&#xff1a;API高效實踐指南 引言 Prompt&#xff08;提示&#xff09;工程是推動大模型能力極限的關鍵手段。合理的Prompt不僅能顯著提升模型輸出的相關性與準確性&#xff0c;在實際落地的API接口開發中同樣起到舉足輕重的作用。本文將系統介…

C++之多態(從0到1的突破)

世間百態&#xff0c;每個人都扮演著不同的角色&#xff0c;都進行著不同的行為。C更是如此&#xff0c;C中也會出現有著不同行為的多種形態的出現&#xff0c;那就讓我們一起進入C的多態世界吧&#xff01;&#xff01;&#xff01; 一. 多態的概念 多態&#xff0c;顧名思義&…

路由器NAT的類型測定

目前所使用的NAT基本都是NAPT&#xff0c;即多端口的NAT技術&#xff0c;因此本文主要是設計了兩種測定路由器NAPT類型的實驗。 實驗環境 設備 主機A&#xff1a;Windows主機B&#xff1a;Windows路由器 軟件 ncWiresharkSocketTools 在局域網內部完成所有測試&#xff0c;完全…