記憶化搜尋顧名思義是在搜尋的過程中通過記錄搜尋的中間狀態從而達到減少重複搜尋的方法,通常用在搜尋樹**現重複子節點的情況。
例題:滑雪
給定乙個r行c列的矩陣,表示乙個矩形網格滑雪場。
矩陣中第 i 行第 j 列的點表示滑雪場的第 i 行第 j 列區域的高度。
乙個人從滑雪場中的某個區域內出發,每次可以向上下左右任意乙個方向滑動乙個單位距離。
當然,乙個人能夠滑動到某相鄰區域的前提是該區域的高度低於自己目前所在區域的高度。
下面給出乙個矩陣作為例子:
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
在給定矩陣中,一條可行的滑行軌跡為24-17-2-1。
在給定矩陣中,最長的滑行軌跡為25-24-23-…-3-2-1,沿途共經過25個區域。
現在給定你乙個二維矩陣表示滑雪場各區域的高度,請你找出在該滑雪場中能夠完成的最長滑雪軌跡,並輸出其長度(可經過最大區域數)。
輸入格式
第一行包含兩個整數r和c。
接下來r行,每行包含c個整數,表示完整的二維矩陣。
輸出格式
輸出乙個整數,表示可完成的最長滑雪長度。
資料範圍
1≤r,c≤300,
0≤矩陣中整數≤10000
輸入樣例:
5 51 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
輸出樣例:
25解題思路:由問題可以發現從某乙個點出發的所有路徑可以抽象成一顆樹,而最遠距離即為該樹的深度。所以只需要列舉所有的起點dfs找到最大深度即可,但是這樣時間複雜度大概是o(n4)顯然不可以。經過觀察發現,有些具有相同子樹的節點會被重複搜尋,所以我們可以在搜尋過程中記錄以每個節點為根節點的子樹的最大深度,當再次搜尋到該節點時進行剪枝。這裡狀態函式儲存的就是以每個節點為根節點的子樹的最大深度,狀態轉移方程即為計算以該節點為根節點的子樹的最大深度的方法。
1)確定狀態函式:f[i][j] 表示從(i, j)可以到達的最遠距離,f[i][j] = max
2)確定狀態轉移方程:從(i, j)出發可能有四個方向可以走,例如向右可以走就是f[i][j] = f[i][j+1] + 1,同理遍歷四個方向取最大值就是最遠距離
#include
#include
#include
#include
using
namespace std;
const
int n =
310;
int n, m;
int h[n]
[n];
int f[n]
[n];
//從(x, y)出發最遠能夠到達的最遠距離
intdfs
(int x,
int y)
;int dy[4]
=;for(
int i =
0; i <
4; i ++
)return v;
}int
main()
動態規劃之記憶化搜尋
一.動態規劃 動態規劃 dynamic programming 與 分治思想 有些相似,都是利用將問題分 為子問題,並通過合併子問題的解來獲得整個問題的解。於 分治 的不同之處在 於,對於乙個相同的子問題動態規劃演算法不會計算第二次,其實現原理是將每乙個計算過的子問題的值儲存在乙個表中。二.記憶化搜...
動態規劃 記憶化搜尋(滑雪)
給定乙個r行c列的矩陣,表示乙個矩形網格滑雪場。矩陣中第 i 行第 j 列的點表示滑雪場的第 i 行第 j 列區域的高度。乙個人從滑雪場中的某個區域內出發,每次可以向上下左右任意乙個方向滑動乙個單位距離。當然,乙個人能夠滑動到某相鄰區域的前提是該區域的高度低於自己目前所在區域的高度。下面給出乙個矩陣...
動態規劃之記憶化搜尋
以 noip 2005 採藥 為例 山洞裡有 m 株不同的草藥,採每一株都需要一些時間 t i 每一株也有它自身的價值 v i 我會給你一段時間 t,在這段時間裡,你可以採到一些草藥。讓採到的草藥的總價值最大。我不會動態規劃,只會搜尋,我就會直接寫乙個粗暴的dfs int n,t int tcost...