动态规划入门理解
自己刚刚学习了一下动态规划的思想,属入门级,总结如下:
Dynamic 动态规划算法通常基于一个或多个初始状态及一个递推公式(状态转移方程)。当前子问题的解将由上一次子问题(或前面某一次)的解推出。使用动态规划来解题只需要多项式时间复杂度, 因此它比回溯法、暴力法等要快许多。
动态规划中,我们要找到某个状态的最优解,然后在它的帮助下,找到下一个状态的最优解。
举例:
问题描述:如果我们有面值为1元、3元和5元的硬币若干枚,如何用最少的硬币凑够11元?
问题分析:我们思考,如何用最少的硬币凑够i元(i<11)。原因:大问题变小,好分析;但小问题的性质必须和大问题一致。
分析步骤:
i=0: d[0] = 0;
i=1:只能使用1元的硬币:d[1] = d[1-1]+1 = d[0]+1 = 1; d[1] = 1;
i=2:只能使用1元的硬币:d[2] = d[2-1]+1 = d[1]+1 = 2; d[2] = 2;
i=3: 使用1元的硬币:d[3] = d[3-1]+1 = d[2]+1 = 3;
使用3元的硬币:d[3] = d[3-3]+1 = d[0]+1 = 1;
so, d[3] = min{d[3-1]+1, d[3-3]+1};d[3] = 1;
i=4: 使用1元的硬币:d[4] = d[4-1]+1 = d[3]+1 = 2;
使用3元的硬币:d[4] = d[4-3]+1 = d[3]+1 = 2;
so, d[4] = min{d[4-1]+1, d[4-3]+1};d[4] = 2;
小结:状态: 凑够i元 所需的硬币数量;
状态只与它前面出现的状态有关,独立于后面的状态。
状态转移方程:描述状态之间是如何转移的,d[i] = min{d[i-Vj]+1},其中 i-Vj >= 0;Vj是下一个可取的决策值。
int MaxValue(int **A, int row, int col) { int **s = new int*[row]; for (int i =0 ; i < row; i++) { s[i] = new int[col]; } int temp=0; for (i = 0; i<row; i++) { for (int j = 0; j < col; j++) { temp = 0; s[i][j] = A[i][j]; if (j>0) { temp = A[i][j-1]; } if (i>0 && A[i-1][j] > temp ) { temp = A[i-1][j]; } } } temp = s[row-1][col-1]; for (i = 0; i < row; i++) { delete s[i]; } delete [] s; s=NULL; return temp; }
举例:
问题描述:LIS:longest increasing subsequence(最长非降序子序列), A[1], A[2]....A[N]
问题分析:
找状态:求A[1], A[2]....A[i](i<N) 中的最长非降序子序列。
状态转移方程:d[i] = max{1, d[j]+1}, j<i, A[j]<=A[i];
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
int LIS(int *arr, int n) { int *d = new int[n]; int len = 1;; memset( d, 0, n); for (int i = 0; i < n; i++) { d[i] = 1; for (int j = 0; j <i; j++) { if(arr[j] <= arr[i] && d[i] < d[j] + 1) { d[i] = d[j] + 1; } } if (d[i] > len) { len = d[i]; } } delete[] d; d = NULL; return len; }
举例:
问题描述:平面上有N*M个格子(A[N][M]),每个格子中放着一定数量的苹果。你从左上角的格子开始, 每一步只能向下走或是向右走,
每次走到一个格子上就把格子里的苹果收集起来, 这样下去,你最多能收集到多少个苹果。
问题分析:
找状态:s[i][j],走到 i,j 时收集到的苹果数量
状态转移方程:s[i][j] = A[i][j] + max(S[i-1][j], if i>0 ; S[i][j-1], if j>0)
代码如下:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
int MaxValue(int **A, int row, int col) { int **s = new int*[row]; for (int i =0 ; i < row; i++) { s[i] = new int[col]; } int temp=0; for (i = 0; i<row; i++) { for (int j = 0; j < col; j++) { temp = 0; s[i][j] = A[i][j]; if (j>0) { temp = A[i][j-1]; } if (i>0 && A[i-1][j] > temp ) { temp = A[i-1][j]; } } } temp = s[row-1][col-1]; for (i = 0; i < row; i++) { delete s[i]; } delete [] s; s=NULL; return temp; }
posted on 2015-09-20 11:12 OrdinaryMiracle 阅读(233) 评论(0) 编辑 收藏 举报