本篇部落客要講分治法、動態規劃法、貪進法、回溯法、分支限界法幾種常用演算法的原理,方便同學們理解每種演算法的道理到底是怎麼回事。
分治法:
將一個難以直接解決的大問題分解為一些規模較小的相同問題各個擊破,分而治之。一般分為三個步驟:分解,求解,合并。和遞迴相似。快速排序是一種典型的分治演算法,將一個大的序列初步排序分解為兩個序列,再對兩個序列再進行排序分解……舉個生活中的例子:比如即將進行的軟考就要開始考試了,考完之後我們每個同學都會有一個成績,之後我們就要對成績進行排名,首先以60分及格分為基準將所有的成績分為兩部分,再對這兩部分分別進行排名,小於60分的同學排一下參見下一次考試,大於60分的選擇全國第50名的分數作為基準再進行分組,一部分是我們班進入全國前50名的,一部分是我們班及格了但是沒有進入全國前50名的——這就是分治法
具體代碼如下:
QUICKSORT(A,p,r){ //排序的主要函數,A為要排序的數組,p數組的開始位置,r為數組的結束位置 if(p<r){ q=PARTITON(A,p,r); //選出數組的一個軸 QUICKSORT(A,p,q-1); QUICKSORT(A,q+1,r); } } PARTITON(A,p,r){ //數組的一個軸的計算函數 x=A[r]; i=p-1; for(intj=p;j<=r-1;j++){ if(A[j]<=x){ i=i+1; 交換A[i]和A[j] } } 交換A[i]和A[r] returni+1; }
動態規劃法:
動態規劃法也是將待求解的問題分為若干個子問題,先求解子問題的解,最後得到原來問題的解。與分治法不同的是,動態規劃法分解的子問題之間往往不是獨立的。分治法分解的子問題相互獨立,一個子問題可能會被求解多次,導致浪費的時間比較多,而動態規劃法就避免了這樣的問題,它的動態就體現到了這裡。只要是被計算過的子問題都要記錄起來,因為將來可能會再次使用。就拿背包問題作為例子來說吧,一個小偷入室盜竊,背包的大小M是一定的,採用動態規劃法就是將背包的大小從1到M逐一的考慮,每種情況可以放什麼物品都記錄起來,當計算背包大小為i的情況的時候,結合背包大小為i-1的情況(動態)選擇合適的物品放到背包中或者維持原來的不變
具體代碼如下:
MaxNutrientValue(n,v,p,M,x){ for i=0 to n nv[i][0]=0 forj=1 to M nv[0][j]=0 for i=1 to n forj=1 to M ifj<p[i] nv[i][j]=nv[i-1][j] elseif nv[i-1][j]>=nv[i-1][j-p[i]]+v[i] nv[i][j]=nv[i-1][j] else nv[i][j]=nv[i-1][j-p[i]]+v[i] j=M fori=n downto 1 if nv[i][j]=nv[i-1][j] x[i]=0 else x[i]=1 j=j-p[i] return x and nv[n][M] }
貪心演算法:
貪心演算法就是僅根據當前的資訊作出選擇,現在作出選擇對將來不管產生什麼影響現在的選擇都不會變化。就是只考慮局部,不考慮整體。典型的例子有“買東西找零錢”,這裡就不細說了。
回溯法:
回溯法就是從根節點出發,以深度優先的方式搜尋解空間,遇到不合格就進行回溯,移動到最近的一個活結點,直到沒有活結點為止。典型的例子有“八皇后”問題
分支限界法:
分支限界法就與回溯法相對應,回溯法是求解目標中滿足約束條件的所有解空間,分支限界法則是找滿足約束條件的一個解(最優解)