一些可以用動態規劃(DP)演算法解決的問題(C )

2021-10-05 06:59:55 字數 4702 閱讀 3795

一、動態規劃問題

暴力搜尋->記憶式搜尋->經典的動態規劃->改進的動態規劃。這也是動態規劃問題的求解步驟。

本質: 利用空間來換取時間。把乙個問題分解為相同的子問題,這些子問題的求解是有順序的,按順序一步一步求解,前面的步驟和決策使得問題的狀態轉移到當前狀態,當前狀態再做出最優的決策,使問題轉移到下乙個狀態,當問題進入最後乙個狀態時的解就是原問題的解。

二、練習題

1、 有陣列penny,penny中所有的值都為正數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定乙個整數aim(小於等於1000)代表要找的錢數,求換錢有多少種方法。

解法(1):按照經典的動態規劃步驟進行,空間複雜度為o(n*aim)

classexchange

for(intj =1;j < aim+1;j++)

for(inti =1;i < n;i++)

}

returndp[n-1][aim];

}

};

classexchange

};

2、有n級台階,乙個人每次上一級或者兩級,問有多少種走完n級台階的方法。

解法: f(n)=f(n-1)+f(n-2)

。如果直接用遞迴式求解,中間有很多重複的計算,

f(n-1)

分支計算過的還得在

f(n-2)

分支計算一次。然後狀態之間的依賴關係是很容易找出了,用動態規劃法,一步一步記錄相鄰兩個狀態即可,下乙個狀態等於這兩個狀態之和。

classgoupstairs

returndp[1]%1000000007;

}

};

3、有乙個矩陣

map,它每個格仔有乙個權值。從左上角的格仔開始每次只能向右或者向下走,最後到達右下角的位

置,路徑上所有的數字累加起來就是路徑和,返回所有的路徑中最小的路徑和。

解法: f(n,m)=min(f(n-1,m),f(n,m-1))+map[n][m]

。遞迴式同樣包含很多重複計算,可以根據狀態之間的依賴關係一步一步計算出來。走到第一行每個格仔的最小路徑和很容易求出。根據第一行可以依次求出第二行,依次進行直到計算到最後一行。

classminimumpath

for(inti =1;i < n;i++)

}

returndp[m-1];

}

};

4、(經典的lis問題)請設計乙個盡量優的解法求出序列的最長上公升子串行的長度。

解法:用dp陣列的dp[i]記錄下以a[i]結尾的遞增子串行中最長的長度,計算dp[i+1]時,遍歷a[0~i]找到比a[i+1]小的元素,再比較與這些元素對應的dp陣列中的值,找到最大的乙個再加1,賦值給dp[i+1]。

class

longestincreasingsubsequence 

dp[i] = ++tempmax;

resmax = max(resmax,dp[i]);

}return

resmax;}};

5、給定兩個字串a和b,返回兩個字串的最長公共子串行的長度。例如,a="1a2c3d4b56",b="b1d23ca45b6a",

123456或者12c4b6都是最長公共子串行。

解法 :

經典的動態規劃題目(lcs)

。利用動態規劃表求解。dp[i][j]表示a[0~i]和b[0~j]的最長公共子串行長度。如果a[i]=b[j], 

則 dp[i][j]一定是dp[i-1][j-1]+1,若

a[i]!=b[j],則

dp[i][j]要麼是dp[i-1][j],要麼是dp[i][j-1]。

(1)常規解法:對第一行和第一列的處理不夠巧妙。

classlcs

}

for(inti =0;i < n;i++)

}

for(inti =1;i < n;i++)

}

returndp[n-1][m-1];

}

};

(2)最優解:dp矩陣多申請了一行和一列,從而將第一行和第一列的處理融合到後序的處理中。

classlcs

else

}

}

returndp[n][m];

}

};

6、乙個揹包有一定的承重cap,有n件物品,每件都有自己的價值,記錄在陣列v中,也都有自己的重量,記錄在陣列w中,每件物品只能選擇要裝入揹包還是不裝入揹包,要求在不超過揹包承重的前提下,選出物品的總價值最大。

解法:經典的

01揹包問題。同樣利用動態規劃表來求解。

(1)常規解法:用常規的二維矩陣dp作為動態規劃表,第一行第一列單獨提前處理。空間複雜度略高。

classbackpack

for(inti =0;i < n;i++)

for(inti =1;i < n;i++)

}

returndp[n-1][cap];

}

};

class

backpack 

}return

dp[cap];}};

二叉樹相關練習題(c++)

經典排序演算法的c++實現

與字串有關的一些典型問題的c++解法

排列組合相關筆試面試題(c++)

與概率相關的演算法題c++解法(附證明過程)

二分查詢的巧妙運用(c++)

位運算在演算法題中的使用(c++)

鍊錶相關練習題(c++)

用例項講解棧和佇列(c++)

一些智力題的c++解法

有關Rujia Liu 動態規劃的 一些總結

1.動態規劃是什麼?就是很高階的大暴力啊!打暴力的時候把值存起來避免重複計算,用來求組合優化問題的 乙個玄學東西 2.如何確定狀態及轉移方程?一般思路先把暴力打出來吧,說不定打打暴力 就像第一次做數字三角,暴力出dp 就把狀態和轉移方程找到了 鄙人覺得做動規前 先打暴力,一是避免翻車,二也能梳理思路...

關於動態規劃的一些經驗與總結

動態規劃是乙個考驗技巧性的演算法,對於動態規劃演算法,幾點經驗。首先是設計狀態,我們肯定是要有乙個一維或多維的狀態的,那麼如何設計它們的意義呢,首先我們可以分析出題目中的一些重要的量,比如當前時間,選了幾個,考慮到了 對於這些狀態我們是要以乙個值來表示這些狀態的最優情況,比如f i j k p,i,...

用PHP實現一些常見的排序演算法

1 氣泡排序 兩兩相比,每迴圈一輪就不用再比較最後乙個元素了,因為最後乙個元素已經是最大或者最小。function maopaosort list return list 2 選擇排序 選定乙個作為基本值,剩下的和這個比較,然後調換位置。function xuanzesort list if pos...