动态时间规整_动态规划-数组系列(10%)
哇呀呀呀呀~~~好!實不相瞞,小弟我就是人稱玉樹臨風勝潘安,一支梨花壓海棠的小淫蟲周伯通!《唐伯虎點秋香》
不同路徑 II?leetcode-cn.com一個機器人位于一個 m x n 網格的左上角 (起始點在下圖中標記為“Start” )。機器人每次只能向下或者向右移動一步。機器人試圖達到網格的右下角(在下圖中標記為“Finish”)。現在考慮網格中有障礙物。那么從左上角到右下角將會有多少條不同的路徑?
輸入: [[0,0,0],[0,1,0],[0,0,0] ] 輸出: 2 解釋: 3x3 網格的正中間有一個障礙物。 從左上角到右下角一共有 2 條不同的路徑: 1. 向右 -> 向右 -> 向下 -> 向下 2. 向下 -> 向下 -> 向右 -> 向右這道題只是在原來的基礎上進行了點修改,可以參看我之前的動態規劃一;而現在為什么改名字了,主要是看到有大佬的刷題路線,各個動態規劃的組成部分。之后都會根據這個分類進行刷題總結,這樣也能有更深刻的體會,也希望大家能有所收獲。天大地大,刷題不斷。
在刷了這個系列很多之后,一開始就是按照固定的模板,定義數組,初始化,狀態轉移,答案。現在終于覺得自己的代碼有些冗余了,然后開始慢慢改進。這道題變得是加了一個復雜物體,那么知道這個位置路徑為0,也就是不可能通過。按照之前的寫法如下:
class Solution:def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:if not obstacleGrid or not len(obstacleGrid[0]):return 0m, n = len(obstacleGrid), len(obstacleGrid[0])dp = [[0] * n for _ in range(m)]if obstacleGrid[0][0] == 0:dp[0][0] = 1for i in range(1, n):if obstacleGrid[0][i] == 1:dp[0][i] = 0else:dp[0][i] = dp[0][i-1]for i in range(1, m):if obstacleGrid[i][0] == 1:dp[i][0] = 0else:dp[i][0] = dp[i-1][0]for i in range(1, m):for j in range(1, n):if obstacleGrid[i][j] == 0:dp[i][j] = dp[i-1][j] + dp[i][j-1]else:dp[i][j] = 0 return dp[-1][-1]完整的按照之前的套路,當我在做初始化的時候,開始發現這樣拆開寫有時候確實很冗余;我們可以嘗試把初始化放在內部,并且嘗試為什么可以放在內部。比如初始化i=0,j=0是容易理解的就是判斷是不是原地就是坑,然后看i=0的時候,在計算dp[i][j] = dp[i][j-1]的時候,就是看看前面有沒有時候,只要有一個時候,那石頭后的都為0;i==0,j==0已經判斷了,那么現在計算dp[i][j-1]的時候是合法的,同樣道理對于計算dp[i-1][j]。看起來很精妙實際上也是按照思路來的,對于雙重循環肯定是先遍歷最里面的,因此就固定初始化第一行。
改進后的:
class Solution:def uniquePathsWithObstacles(self, obstacleGrid: List[List[int]]) -> int:if not obstacleGrid or not len(obstacleGrid[0]):return 0m, n = len(obstacleGrid), len(obstacleGrid[0])dp = [[0] * n for _ in range(m)]for i in range(m):for j in range(n):if obstacleGrid[i][j] == 0:if i == 0 and j == 0:dp[0][0] = 1elif i == 0:dp[i][j] = dp[i][j-1]elif j == 0:dp[i][j] = dp[i-1][j]else:dp[i][j] = dp[i-1][j] + dp[i][j-1]else:dp[i][j] = 0 return dp[-1][-1]不過運行的實際結果是,第一個擊敗了90%左右的,第二個只擊敗了50%左右的。這里講到路徑的條數或者最短路徑,想起了之前做時間序列分析的時候遇到的DTW算法。實際上這種算法只要是做時間序列的分類聚類,最優的算法基本上都是在此基礎之上,而這個算法的基礎就是最短路徑。
DTW(Dynamic Time Warping)動態時間規整
DTW可以計算兩個時間序列的相似度,尤其適用于不同長度、不同節奏的時間序列(比如不同的人讀同一個詞的音頻序列)。DTW將自動warping扭曲 時間序列(即在時間軸上進行局部的縮放),使得兩個序列的形態盡可能的一致,得到最大可能的相似度。
傳統的都是基于歐式距離的一對一對齊,只要一個位置稍稍移動,得到的結果就會變得很差,而這種算法就是為了解決這個問題。
實際的代碼:
function dist = dtw(t,r) n = size(t,1); m = size(r,1); % 幀匹配距離矩陣 d = zeros(n,m); for i = 1:nfor j = 1:md(i,j) = sum((t(i,:)-r(j,:)).^2);end end % 累積距離矩陣 D = ones(n,m) * realmax; D(1,1) = d(1,1); % 動態規劃 for i = 2:nfor j = 1:mD1 = D(i-1,j);if j>1D2 = D(i-1,j-1);elseD2 = realmax;endif j>2D3 = D(i-1,j-2);elseD3 = realmax;endD(i,j) = d(i,j) + min([D1,D2,D3]);end end dist = D(n,m);而它核心的實際上就是D(i,j)=d(i,j)+min([D1,D2,D3])一句,就和維特比算法一樣,如果只是放在動態規劃里,實際上大家覺得都有些low了,對應到力扣上也就中等難度。但是難的是將這種方法用在特定的問題上,并且優秀地解決了大問題。值得一提的是維特比算法也是動態規劃的思想,大概和之前動態規劃系列-4里的三角形里的最小值一樣,而維特比則是尋找最大概率。
這兩個算法在各自領域的影響實在是太大了,不得不讓我對學習動態規劃有了更深刻的認識。
參考博客:
所有題目均來自于力扣
https://zhuanlan.zhihu.com/p/32849741
https://www.cnblogs.com/luxiaoxun/archive/2013/05/09/3069036.html
總結
以上是生活随笔為你收集整理的动态时间规整_动态规划-数组系列(10%)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 隐形牙套咬胶的作用是什么?
- 下一篇: 海信空调型号