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