两个简单的动态规划问题,0-1背包和最大不相邻数累加和,附递归c代码
最近面試經(jīng)常被問到動態(tài)規(guī)劃,所以自己做了一個總結(jié),希望能進行深入的理解然后嘗試能不能找到通用的解決手段。我覺得動態(tài)規(guī)劃思想好理解,難的是怎么找出全部并且合理的子問題和出口。
我一般把問題分為兩類,一類是有兩個變化值,對應(yīng)的我們要設(shè)一個二維數(shù)組記錄(比如背包問題,每一步不僅物品發(fā)生變化,背包容量也改變);一類是一個變化值,對應(yīng)的我們只需設(shè)置一個一維數(shù)組(比如只有一個變量改變的最值問題)。
然后確定該問題的子問題,找出狀態(tài)轉(zhuǎn)移方程。這里有一個小技巧,一般都是從數(shù)組最后一個元素開始逐步向前遞歸(思考方式也就是從最后一個開始思考),然后找遞歸出口即可。
從0-1背包問題說起:
一個背包總?cè)萘繛閃, 現(xiàn)在有N個物品, 第i個物品容量為w[i], 價值為v[i], 物品只能取或不取,現(xiàn)在往背包里面裝東西, 怎樣裝才能使背包內(nèi)物品總價值最大?
首先我們看到每一次選取,物品個數(shù)和背包容量都會發(fā)生變化,所以考慮設(shè)一個二維數(shù)組B[i][j],表示i個物品和容量為j的背包的問題,然后找它的子問題:
1 第i個體積太大,放不進去 W不變,i變?yōu)閕-1。問題轉(zhuǎn)化為i-1個物品和容量為W背包的問題
2 第i個體積不大,可以放進去
(1)放進去 ? ?W變?yōu)閃-w[i],i變?yōu)閕-1 問題轉(zhuǎn)化為i-1個物品和容量為W-w[i]背包的問題
(2)不放進去 W不變 i變?yōu)閕-1 ?問題轉(zhuǎn)化為i-1個物品和容量為W背包的問題
除此以外應(yīng)該沒有其他可能了,所以我們找出了所有的子問題
寫出c代碼
#include<stdio.h> #include <stdlib.h> int B[6][20]; int w[6] = { 0, 2, 3, 4, 5, 9 }; int v[6] = { 0, 3, 4, 5, 8, 10 };int bag(int n, int W){if (n == 0 || W == 0){return 0;}else{if (w[n] > W){return bag(n - 1, W);}else{return (bag(n - 1, W - w[n]) + v[n]) > bag(n - 1, W) ? (bag(n - 1, W - w[n]) + v[n]) : bag(n - 1, W);}} }int main() {printf("hello world!\n");printf("%d", bag(6, 20));system("pause");return 0; }
?
接下來再來一個一維數(shù)組的:
從一個序列中選出互不相鄰的幾個數(shù),是它們的累加和最大。比如[3,2,1,9,4,2]最大的就是3+9+2=14
求解:
可以看到,每選一個數(shù),這個序列就會改變一次(因為不能再選與被選數(shù)相鄰的),不存在其他變量,所以我們設(shè)一個一維數(shù)組num[i],i表示長度為i的數(shù)組(也可以說最后元素下標為i的數(shù)組)能選出的最大累加和,設(shè)第i個的值為v[i]。
然后找它的子問題:
1 選擇第i個 ?因為不能選擇第i-1個數(shù),所以問題轉(zhuǎn)化為長度為i-2的數(shù)組+v[i]的子問題
2 不選擇第i個,問題轉(zhuǎn)化為長度為i-1的數(shù)組的子問題
我們只要找出兩者最大即可
代碼:
#include<stdio.h> #include <stdlib.h> int v[6] = { 3, 2, 1, 9, 4, 2 };int add(int *value,int N){if (N == 0){return 0;}else if (N == 1){return value[0];}else{return add(value, N - 1) > (add(value, N - 2) + value[N - 1]) ? add(value, N - 1):(add(value, N - 2) + value[N - 1]);} }int main() {printf("%d", add(v,6));system("pause");return 0; }這兩個還是比較簡單的,但是我希望能從簡單問題找出通用套路。如果大家有其他的更好的思路可以給我留言。
?
轉(zhuǎn)載于:https://www.cnblogs.com/dylan9/p/8723474.html
總結(jié)
以上是生活随笔為你收集整理的两个简单的动态规划问题,0-1背包和最大不相邻数累加和,附递归c代码的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: android -------- NDK
- 下一篇: Layabox 常用操作