Optimal Path

Optimal Path

請找到上緣到下緣的最佳路線:數字總和最小的路線。

只能走往左下、下、右下(來自左上、上、右上)

遇事不決,首先枚舉。

直覺的方式是回溯法。枚舉所有路線,從中找出最佳路線。

地圖的長寬是H和W。格子的數量是HW。路線的數量是W⋅3⋅3⋅...⋅3 = W⋅3ᴴ⁻¹再少一些,左緣與右緣只會衍生兩條路線。

時間複雜度O(W⋅3ᴴ⁻¹) = O(W⋅3ᴴ)。1/3是常數倍率,O()無視常數倍率。

更好的方式是動態規劃。原問題,刪除下緣,形成子問題。

源頭的子問題:只剩上緣。

計算順序:從上往下,逐層計算。

時間複雜度O((HW)⋅3) = O(HW)。3是常數倍率,O()無視常數倍率。

UVa 116 10564

只能走往下一層任一格(來自上一層任一格)

枚舉三格改成枚舉一層。

時間複雜度O((HW)⋅W)。

然而,上一層的最小值,通通相同。大可不必重複計算。

動態規劃化簡成貪心法。每一層的最小值,通通加總。

時間複雜度降為O(HW)。

只能走往下、左、右(來自上、左、右)

因為無法順利刪除下緣,所以只好深入分析問題。

走往左或右:一、可能左右單向行走,二、可能左右來回行走。

左右單向行走,得以順利刪除下緣:來源改成上一層任一格,再追加一段走過來的距離(區間和)。區間和等於累積和相減。累積和可以事先計算。

左右來回行走:甲、可能讓總和增加,乙、可能讓總和不變,丙、可能讓總和減少。

總和增加或不變,不適合來回行走,只適合單向行走。問題化作單向行走,問題已然解決。

總和減少,永遠走不完,問題的答案是無限小。檢查左右相鄰兩格數字總和是否為負值。

問題的分析流程如上所示。程式碼的寫作流程又是另外一回事。我不想囉嗦,大家自己琢磨吧。

時間複雜度O((HW)⋅W)。

只能走往上、下、左、右(來自上、下、左、右)

問題化作最短路徑問題。請見本站文件「Shortest Path」。

點有權重,邊無權重。點權重挪至入邊權重。

時間複雜度O((HW)²)。

雜談

題目稍微修改,解答大幅改變。沒有徵兆,毫無規律。

正是因為變化多端,沒辦法一語帶過,才需要寫下這份筆記。正是因為變化多端,沒辦法一勞永逸,才誕生工程師這樣的職位。

對於喜歡益智遊戲的人,變化是樂趣。對於處理實際問題的人,變化是困擾。人人都有不同想法。然而,天下本無事,庸人自擾之。即便不去學習這些變化,其實也沒什麼大不了。如果你認為這些變化無關緊要,那麼恭喜你,你很自由。

Seam Carving

Seam Carving

這是圖片處理的演算法。縮小圖片尺寸、同時維持圖片觀感。

🡲

找到變化最小的路線,然後刪除路線。圖片寬度縮小1像素。

想讓圖片寬度縮小更多,那就再多找幾條路線。

一個位置的變化程度,設定為「它跟周圍顏色的差異」,通常採用Sobel Operator。每個位置的變化程度,事先計算、填入格子。「變化最小的路線」化作「數字總和最小的路線」。

「找到一條路線,刪除一條路線,重複數次」比較簡單,大家都這樣做。「一口氣找到大量路線、刪除大量路線」相當困難,演算法更加複雜,時間複雜度極高,沒有人這樣做。

實況

Seam Carving是影像處理軟體的標準配備。Photoshop軟體即內建Seam Carving。美術人員運用照片素材,進行海報設計、廣告創作、場景建造、特效製作,或多或少用到它。

Seam Carving已經申請專利。照理來說,我不可以介紹。

雜談

我先介紹Optimal Path、才介紹Seam Carving。透過這樣的編排順序,想必讀者自然而然意識到:先學好Optimal Path、才能學好Seam Carving。先精通基礎,才發掘應用。

凡是教科書、學校課程,都是如此編排。數學教科書尤其重視編排順序,越通順越優秀。

然而實際情況恰恰相反:大家先想到Seam Carving,才去深究Optimal Path。先解決問題,才歸納原理。

大家嘗試縮小圖片尺寸。因為問題太過困難,所以問題需要簡化。大家嘗試各種簡化方式,其中一種簡化方式是「圖片寬度僅縮小1像素」,接著便想到了「變化最小的路線」。計算每個位置的變化程度,這個問題就可以簡單描述為「數字總和最小的路線」。深究之後,發現走往三方向(左下、下、右下)是最合適的方式。以上就是實際情況。

各位在本站當中、在教科書當中、在學校課程當中獲得的知識,都是貨真價實的知識,幾乎都有實際用途(除非作者犯傻)。然而,各位在本站當中、在教科書當中、在學校課程當中的學習歷程,幾乎都是反其道而行之。你越適應它們,你就越偏離實際情況。

詳細來說,解決問題有兩種策略:bottom-up和top-down。bottom-up從公理出發,推導定理、發掘性質。top-down從問題出發,分析細節、找到根源。兩者方向相反。

各位在本站當中、在教科書當中、在學校課程當中,只會接觸到bottom-up。然而,實際情況大多是top-down。甚至是雙向輪流前進,直到兩端相通。

希望大家能夠明白自身處境,避免偏離實際情況。

雖然我將這段文字編排於文末雜談,但是實際情況你懂的。

Optimal Planning

Optimal Planning

請找到起點到終點的最佳路線:數字總和最小的路線。

剛好走K步

一、走過的地方可以再走(地點可以重複):如同先前章節,一步對應一層。時間複雜度O(NK)。

二、走過的地方不可以再走(地點不可重複):還是可以動態規劃。狀態是走過的地點集合、路線的結尾。時間複雜度O(2ᴺ NK)。

不限制步數

一、走過的地方可以再走(地點可以重複):原問題化作最短路徑問題。請見本站文件「Shorest Path」。

甲、如果圖上無負環,則是P問題。時間複雜度O(N²)。

乙、如果圖上有負環,答案是負無限大。時間複雜度O(N²)。

二、走過的地方不可以再走(地點不可重複):原問題化作最短點互斥路徑問題。請見本站文件「Shortest Vertex-disjoint Path」。

甲、如果圖上無負環,則是P問題。時間複雜度O(N²)。

乙、如果圖上有負環,則是NP-complete問題。以動態規劃紀錄走過的地點集合、路線的結尾。時間複雜度O(2ᴺ N²)。

找到數字差異最小的路線

給定一串數字,找到最符合這串數字的路線。

首先必須仔細定義何謂符合!

符合:差異盡量小。兩個數字的差異:兩個數字相減、取絕對值。一條路線的差異:差異的總和。

如此一來,差異大小填到對應路段,問題化作「找到數字總和最小的路線」。每一層數字皆不同。

Viterbi Decoding

Viterbi Decoding

這是訊號處理的演算法。訊號是一長串二進位數字。訊號傳輸途中,經常受到干擾,導致訊號變動。為了獲得正確訊號,因而發明了一套流程:編碼、傳輸、解碼。

編碼(原始訊號進行加工):根據二進位數字,走出一條路線。

解碼(加工訊號進行還原):找到差異最小的路線。差異是相異位數數量。

解碼時,找到差異最小的路線,以便獲得正確訊號。

編碼時,適度增加訊號長度,以便包容差異。

兩造使用相同地圖。每個地點只有兩條出路,對應0和1。

實況

Viterbi Decoding曾經是行動電話系統的標準配備。所有手機均內建Viterbi Decoding。每當大家講手機,總是用到它。

Viterbi Decoding專利已經過期。照理來說,大家都能引用。