[leetcode]1631. 最小體力消耗路徑(bool類型dfs+二分答案/記憶化剪枝/并查集Kruskal思想)

題目鏈接

題意

給定 n × m n\times m n×m地圖 要從(1,1) 走到 (n,m)
定義高度絕對差為四聯通意義下相鄰的兩個點高度的絕對值之差
定義路徑的體力值為整條路徑上 所有高度絕對差的max
求所有路徑中 最小的路徑體力值是多少

方法1

這是我一開始自己寫的記憶化剪枝
比較暴力 時間復雜度很高 但是能勉強通過

思路

dfs枚舉每條路徑 對ans取min
但是會超時 那么加上記憶化剪枝

Code

void cmax(int &a,int b){a=max(a,b);};
void cmin(int &a,int b){a=min(a,b);};
const int N=110;
int dx[4]={-1,0,1,0},dy[4]={0,1,0,-1};
int g[N][N],dp[N][N];//dp表示從(1,1)走到(i,j)的最小體力值
bool vis[N][N];
int n,m;class Solution {
public:int ans=0x3f3f3f3f;//ans必須定義在類內部 因為定義在全局會被上一個測試用例修改int minimumEffortPath(vector<vector<int>>& heights) {n=heights.size(),m=heights[0].size();memset(dp,0x3f,sizeof dp);for(int i=0;i<n;i++){for(int j=0;j<m;j++){g[i+1][j+1]=heights[i][j];}}vis[1][1]=1;dfs(1,1,0);return ans;}void dfs(int x,int y,int res){if(res>ans) return;if(x==n&&y==m){cmin(ans,res);return;}for(int i=0;i<4;i++){int tx=x+dx[i],ty=y+dy[i];if(tx<1||tx>n||ty<1||ty>m||vis[tx][ty]) continue;int now=max(abs(g[tx][ty]-g[x][y]),res);if(dp[tx][ty]<=now) continue;//如果從(tx,ty)這個點已經搜過了 //并且之前存的比當前搜的更優 那么就放棄當前這個點dp[tx][ty]=now;//當前更優 vis[tx][ty]=1;dfs(tx,ty,now);vis[tx][ty]=0;}}   
};

方法2

思路

最大值最小化 ->二分答案
對路徑體力值二分 每次check就是dfs一下能不能在這個高度絕對差不超過mid 的情況下走到終點

Code

#define pii pair<int,int>
#define ar2 array<int,2>
#define ar3 array<int,3>
#define ar4 array<int,4>
#define endl '\n'
void cmax(int &a,int b){a=max(a,b);};
void cmin(int &a,int b){a=min(a,b);};
const int N=110,MOD=1e9+7,INF=0x3f3f3f3f;const long long LINF=LLONG_MAX;const double eps=1e-6;
int dx[]={-1,0,1,0},dy[]={0,1,0,-1};
int n,m,g[N][N];
bool vis[N][N];bool dfs(int x,int y,int k){if(x==n&&y==m) return 1;for(int i=0;i<4;i++){int tx=x+dx[i],ty=y+dy[i];if(tx<1||tx>n||ty<1||ty>m||vis[tx][ty]) continue;int d=abs(g[x][y]-g[tx][ty]);if(d<=k){vis[tx][ty]=1;bool flag=dfs(tx,ty,k);if(flag) return 1;}}return 0;
}class Solution {
public:int minimumEffortPath(vector<vector<int>>& heights) {n=heights.size(),m=heights[0].size();for(int i=0;i<n;i++){for(int j=0;j<m;j++){g[i+1][j+1]=heights[i][j];}}int l=-1,r=1e6+1;while(l+1!=r){int mid =l+r>>1;memset(vis,0,sizeof vis);vis[1][1]=1;if(dfs(1,1,mid)) r=mid;else l=mid;}return r;}
};

實現細節

  • 每次二分要初始化vis數組 并且注意要把起點設為true
  • 重點看bool類型dfs的實現
    • bool dfs(int x,int y,int k)表示從 (x,y)出發 以k為限制能否到達終點
    • 與常見的dfs枚舉路徑方案不同 這里不需要枚舉全部方案 而是只需要找到一個方案能夠到達終點就可以
    • 不需要回溯 把vis[tx][ty]=0 因為一旦這個點可以走(從(x,y)到(tx,ty)不超過k到限制) 那么就會被標記為true 然后dfs往下走
    • 如果從(tx,ty)不能到終點 那么dfs會返回false 所以這個點就沒有價值了 不需要回溯 如果標記回去 從別的點再次走到這個點是沒有意義的 這個點已經搜過了 不可能走到終點
    • 如果dfs從(tx,ty)往下搜 能到終點 就立刻返回true 如果四聯通都走了一遍也沒return true 那么說明不行 就return false

方法3

思路

Kruskal的思想
把每條邊存下來 按邊權排序
用并查集維護 一旦起點和終點在一個聯通塊內 就返回此時的邊權(因為排序過了 一定是最大的邊權)


這里不需要關心每一步具體是怎么走的
只需要維護每個點的聯通關系即可 只要起點和終點聯通 就代表一條完整的路徑出現了 這個思路太妙了 實現起來很快

Code

void cmax(int &a,int b){a=max(a,b);};
void cmin(int &a,int b){a=min(a,b);};
const int N=110;
int p[N*N];
int n,m;int find(int x){if(p[x]!=x) p[x]=find(p[x]);return p[x];
}struct node{int w,u,v;
};class Solution {
public:int minimumEffortPath(vector<vector<int>>& g) {n=g.size(),m=g[0].size();for(int i=0;i<=n*m;i++) p[i]=i;//建圖vector<node>edges;for(int i=0;i<n;i++){for(int j=0;j<m;j++){int id=i*m+j;if(i>0){edges.push_back((node){abs(g[i-1][j]-g[i][j]),id-m,id});}if(j>0){edges.push_back((node){abs(g[i][j-1]-g[i][j]),id-1,id});}}}sort(edges.begin(),edges.end(),[](const auto& e1,const auto& e2){return e1.w<e2.w;});int ans=0;for(auto[w,u,v]:edges){int uu=find(u),vv=find(v);p[vv]=uu;//不要寫成uu=p[vv];if(find(0)==find(n*m-1)){ans=w;break;}}return ans;}};

實現細節

關鍵是在建圖
兩重循環遍歷 每個點都跟他上面以及左邊的點建邊(如果有的話)
這樣就很方便的 不重不漏地把所有的邊都建起來了
存邊的時候節點編號做一個簡單的狀態壓縮即可

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

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

相關文章

DeepSeek寫打臺球手機小游戲

DeepSeek寫打臺球手機小游戲 提問 根據提的要求&#xff0c;讓DeepSeek整理的需求&#xff0c;進行提問&#xff0c;內容如下&#xff1a; 請生成一個包含以下功能的可運行移動端打臺球小游戲H5文件&#xff1a; 要求 可以重新開始游戲 可以暫停游戲 有白球和其他顏色的球&am…

webpack使用詳細步驟

項目描述 本項目 webpack 的基本使用。 webpack 官方&#xff1a;https://webpack.docschina.org/concepts/ Element-plus 官方&#xff1a;https://element-plus.sxtxhy.com/zh-CN/ Vue3 官方&#xff1a;https://cn.vuejs.org/ 項目組成明細 每個步驟完成后重新執行 npm run …

【STM32實物】基于STM32的太陽能充電寶設計

基于STM32的太陽能充電寶設計 演示視頻: 基于STM32的太陽能充電寶設計 硬件組成: 系統硬件包括主控 STM32F103C8T6、0.96 OLED 顯示屏、蜂鳴器、電源自鎖開關、溫度傳感器 DS18B20、繼電器、5 V DC 升壓模塊 、TB4056、18650鋰電池、9 V太陽能板、穩壓降壓 5 V三極管。 功能…

【記一次】AI微調訓練步數計算方式

llama微調訓練步數計算方式,以下數據為假設 一、關鍵參數解析 總樣本數&#xff1a;Num examples 1,047 表示訓練數據集包含 1,047 個樣本。 訓練輪數&#xff1a;Num Epochs 300 表示整個訓練集將被遍歷 300 次。 總批次大小&#xff1a;Total train batch size 80 表示…

python-selenium 爬蟲 由易到難

本質 python第三方庫 selenium 控制 瀏覽器驅動 瀏覽器驅動控制瀏覽器 推薦 edge 瀏覽器驅動&#xff08;不容易遇到版本或者兼容性的問題&#xff09; 驅動下載網址&#xff1a;鏈接: link 1、實戰1 &#xff08;1&#xff09;安裝 selenium 庫 pip install selenium&#…

yaffs

YAFFS&#xff08;Yet Another Flash File System&#xff09;是專為NAND閃存設計的日志結構文件系統&#xff0c;其核心原理圍繞NAND閃存的特性優化數據管理。以下是其關鍵原理的詳細說明&#xff1a; 1. NAND閃存適配 寫入限制&#xff1a;NAND閃存需按頁寫入&#xff08;通…

git的底層原理

git的底層原理 三段話總結git&#xff0c; 1. 工作原理&#xff1a;git管理是一個DAG有向無環圖&#xff0c;HEAD指針指向branch或直接指向commit&#xff0c;branch指向commit&#xff0c;commit指向tree&#xff0c;tree指向別的tree或直接指向blob。 2. git所管理的一個目錄…

【計算機網絡原理】選擇題+簡答題

文章目錄 選擇題網絡基礎IP網絡拓撲 OSI七層模型協議HDLCTCP/IP 交換技術網絡安全數字簽名 算法與策略 簡答題UDPTCP 選擇題 網絡基礎 下列域名中&#xff0c;屬于國際頂級域名的是&#xff08;&#xff09; A. us B. tom C. edu D. int 下列關于光纖傳輸介質的敘述中錯誤的是…

Android數據加密方案

Android數據加密方案 前言 在移動應用開發中,數據安全是一個永恒的話題。Android應用中往往需要存儲和傳輸敏感數據,如用戶密碼、支付信息、個人隱私等。本文將深入介紹Android平臺上的數據加密方案,幫助開發者構建安全可靠的數據保護機制。 基礎知識 1. 加密算法分類 …

神聖的綫性代數速成例題13. 非齊次方程組解的性質、非齊次方程組解的討論

綫性空間的維數&#xff1a; 若綫性空間中存在一組綫性無關的矢量&#xff0c;使得中的任意矢量 都可以由綫性表示&#xff0c;則稱為綫性空間的維數&#xff0c;記作&#xff0c;稱為的一組基。 基與座標變換&#xff1a; 設和是維綫性空間的兩組基&#xff0c;且&#xff0c;…

github代理 | 快速clone項目

代理網址&#xff1a; https://ghproxy.com/ https://ghproxy.com/代理網址&#xff1a; https://ghproxy.com/ 比如需要克隆的項目git地址為&#xff1a;https://github.com/AUTOMATIC1111/stable-diffusion-webui.git git clone https://ghproxy.com/https://github.com/AUTO…

Kafka集成Debezium監聽postgresql變更

下載postgres的插件&#xff1a;https://debezium.io/documentation/reference/2.7/install.html 2.7版本支持postgresql12數據庫。 debezium-connector-postgres-2.7.4.Final-plugin.tar.gz 上傳插件并解壓 mkdir /usr/local/kafka/kafka_2.12-2.2.1/connector cd /usr/local…

『uniapp』簡單文本復制文字 富文本內容復制文字(詳細圖文注釋)

目錄 text組件錯誤代碼示例成功代碼總結 歡迎關注 『uniapp』 專欄&#xff0c;持續更新中 歡迎關注 『uniapp』 專欄&#xff0c;持續更新中 text組件 官方文檔可知app端用selectable可實現文本選中進而可復制,也就是說text標簽內部的文本就可以復制了 https://uniapp.dclou…

RestTemplate和RPC區別

RestTemplate是Spring框架中用于進行RESTful風格的HTTP請求的模板類&#xff0c;通常用于與外部服務進行通信。它基于HTTP協議&#xff0c;使用GET、POST、PUT、DELETE等HTTP方法來進行通信&#xff0c;傳輸的數據通常使用JSON或XML格式。它是一種基于資源的通信方式&#xff0…

算法模型從入門到起飛系列——背包問題(探索最大價值的掘金之旅)

文章目錄 前言一、背包問題溯源&#xff08;動態規劃&#xff09;1.1 動態規劃的概念1.2 動態規劃的基本步驟1.3 動態規劃的實際應用 二、背包問題2.1 背包問題衍生2.2 0-1背包2.2.1 0-1背包描述2.2.2 0-1背包圖解2.2.3 0-1背包代碼刨析 2.3 完全背包2.3.1 完全背包描述2.3.2 完…

Python實現爬蟲:天氣數據抓取(+折線圖)

一、基本架構 1、URL管理器&#xff1a;爬蟲的調度中樞 核心職責 功能說明URL去重防止重復抓取URL優先級管理控制抓取順序&#xff08;廣度優先/深度優先&#xff09;斷點續爬支持持久化存儲抓取狀態分布式協同多節點共享URL隊列 2、網頁下載器&#xff1a;數據獲取的引擎 功…

DFS刷題

洛谷P2089烤雞 #include<iostream> using namespace std; const int N 20, M 1000010; int ans[N]; int dp[M][N]; int n, count; void dfs(int x, int sum){if(sum > n)return;if(x > 10){if(sum n){count;for(int i 1; i < n; i)dp[count][i] ans[i];}r…

《Operating System Concepts》閱讀筆記:p460-p4470

《Operating System Concepts》學習第 36 天&#xff0c;p460-p4470 總結&#xff0c;總計 11 頁。 一、技術總結 無。 二、英語總結(生詞&#xff1a;3) 1.lifespan (1)lifespan: life span(“the period of time that sth exists or happens”) c. 也寫作 life-span, …

stratis,容器podman

一、stratis 1.stratis可以實現動態的在線擴容&#xff0c;lvm雖然也可以實現在線擴容&#xff0c;但是是需要人為的手動擴容。 2.stratis不需要手動格式化&#xff0c;自動會創建文件系統&#xff08;默認是xfs&#xff09; 1. 安裝stratis軟件包 yum list | grep stratis…

音頻焦點 Android Audio Focus

Android 音頻焦點詳解 音頻焦點&#xff08;Audio Focus&#xff09;是 Android 系統用于協調多個應用同時訪問音頻輸出的機制。當多個應用需要播放音頻時&#xff0c;音頻焦點確保用戶聽到的內容不會混亂&#xff08;如多個音樂應用同時播放&#xff09;。以下從核心概念、使…