求矩陣的最大路徑的問題
題目描述:有一個m×n的矩陣,現要從左下角走到右上角,並且方向只能是向上或者向右,
現規定一條路徑的權值為走此路徑所經過的值的和。給定一個矩陣,請找出權值最大的一條
路徑。
Example:
2 5 6
3 9 4
7 9 1
所找到的路徑為7->9->9->5->6,權值為36。
首先我們來介紹一下動態規劃的思想:
動態規劃程式設計中,我們主要利用了問題的兩個性質:最優子結構和子問
題重疊。最優子結構指問題的最優解包含了子問題的最優解,它是動態規劃方法可
行的理論基礎。而一個問題具有子問題重疊性質是指用遞迴演算法自頂向下解這個問
題時,並不總是產生新的子問題,有些子問題被重複求解多次。
因為最優子結構性質,動態規劃求問題最優解時,可以轉化為求子問題的最優
解,而對解決過的問題,動態規劃則記錄它的結果,當再次遇上已解決的問題,就
可以直接利用結果。子問題重疊性質保證了這樣做是有意義的。但一般的搜尋技術
,對於某個子問題不管是否已經解決過,只要遇上,就會再次對這個子問題進行求
解。
很明顯,動態規劃與一般搜尋技術最大不同的地方就是記錄了已求解過的問題
的結果。這裡包含了兩個方面的內容 :子問題的記錄和子問題結果的記錄。其中
,子問題的記錄是最重要,也是最為複雜的,它就是通常我們所說的狀態表示。
通常我們用一個數、一組數或一個向量來實現狀態表示。但無論採取什麼方法,從
動態規劃的原理來看,狀態表示要滿足兩個要求:正確、合理描述子問題和描述的
子問題滿足最優子結構性質;從演算法實現角度來看,狀態表示必須能夠用基本資料
結構實現並且能滿足空間要求。
現在我們來看上面的這個問題:(path[][]是矩陣的描述)
狀態表示: 用maxpath[i][j]表示走到第i行第j列的最大權值,那麼maxpath[i][j]的最優解
包含子問題maxpath[i-1][j]和maxpath[i][j+1]的最優解,然後我們採取倒推法,則可得到我
們的狀態轉移方程:
maxpath[i][j] = MAX{ maxpath[i-1][j], maxpath[i][j+1] } + maxpath[i][j];
maxpath[0][n-1] = path[0][n-1];
這樣,最大的路徑權值可以通過比較底層的分數求得。
一般情況下,我們找到的狀態表示應能刻劃子問題的特徵,困難的是如何找到描述
的子問題能滿足最優子結構性質的狀態表示,而這一點恰恰是決定該問題能否應用
動態規劃方法的重要因素。狀態表示1-1描述的問題是正確的,但它不能滿足最優
子結構性質,使得無法用它來建立動態規劃數學模型。狀態分析的過程實際上是分
析問題最優子結構的過程,不同的狀態表示正是從不同的角度去試圖刻劃問題的最
優子結構。只有狀態表示描述的子問題能滿足最優子結構性質,我們才能在此基礎
上正確的建立起動態規劃數學模型。
我們看看此題的具體解答:(Java描述)
public class MaxPath
{
private void print(int path[][])//列印路徑
{
for(int i=0;i<path.lengt h;i++)
{
for(int j=0;j<path[i].length;j++)
{
System.out.print (path[i][j]+" ");
}
System.out.println ("");
}
}
public int findMaxPath(int path[][])
{
for(int i=path[0].length-2;i>=0;i--)//第一行的值
{
path[0][i]+=path[0][i+1];
}
for(int i=1;i<path.length;i++) //最後一列的值
{
path[i][path[i].length-1]+=path[i-1][path[i-1].length-1];
}
for(int i=1;i<path.length;i++)//倒推法,利用上面的公式
{
for(int j=path[i].length-2;j>=0;j--)
{
if(path[i-1][j]>=path[i][j+1])
{
path[i][j]=path[i][j]+path[i-1][j];
}
else
{
path[i][j]=path[i][j]+path[i][j+1];
}
}
}
print(path);
return path[path.length-1][0];//最後位置的值即為要求的最大權值
}
public static void main(String args[])
{
int[][] path={{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,16}
};
System.out.println (new MaxPath().findMaxPath(path));
}
}