动态规划
基本思想:
动态规划(Dynamic programming,DP),通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量: 一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。
步骤:
1. 找出最优解的性质,并刻画其结构特征
2. 递归定义最优值
3. 以自底向上的方式计算出最优值
4. 根据计算最优值得到的信息,构造一个最优解
重要性质:
1. 最优子结构
2. 重叠子问题
范例:
1. 最短路径
#include<iostream> #include<string.h> using namespace std; #define LENGTH 5 /* matrix 图 minPath 临时数组 visit 是否访问 LENGTH 点数 MinDistance(v) 出发点到v的最短距离 Fk(u) 表示从Sk中的点u到终点的距离 Sk 表示某点的子边集合 */ int matrix[LENGTH][LENGTH] = { 0,10,0,30,100, 0,0,50,0,0, 0,0,0,0,10, 0,0,20,0,60, 0,0,0,0,0, }; int minPath[LENGTH]; bool visit[LENGTH]; /* 递归深度搜索 */ int MinDistance(int v) { if(minPath[v] > 0) return minPath[v]; if(v == LENGTH -1) return 0; int min = 1000,t,j; for(int i = 0;i < LENGTH;i++) { if(matrix[v][i] > 0 && visit[i] == false) { visit[i] = true; /* 动态方程式 MinDistance(u) = min{w(u,v) + MinDistance(v)} */ t = MinDistance(i) + matrix[v][i]; visit[i] = false; if(min > t) { min = t; j = i; } } } minPath[v] = min; return minPath[v]; } /* 迭代搜索 */ int MinDistanceEx() { minPath[0] = 1000; for(int i = 0;i < LENGTH;i++) { for(int j = 0;j < LENGTH;j++) { if(matrix[i][j] > 0) { /* 状态方程式 Fk(u) = min{w(u,v) + Fk+1(v)} */ if(i > 0) { /* 刷新自己到出发点最短距离 */ if(minPath[j] > minPath[i] + matrix[i][j]) { minPath[j] = minPath[i] + matrix[i][j]; } /* 刷新其他结点到出发点最短距离 */ for(int k = 0;k < LENGTH;k++) { if(k != j && matrix[j][k] > 0 && minPath[k] > minPath[j] + matrix[j][k]) { minPath[k] = minPath[j] + matrix[j][k]; } } } else { minPath[j] = matrix[i][j]; } } } } return minPath[LENGTH-1]; } int main(void) { for(int i = 0;i < LENGTH;i++) { trace[i] = 0; minPath[i] = 1000; visit[i] = false; } //int minD = MinDistance(0); int minD = MinDistanceEx(); std::cout<<"minD:"<<minD<<std::endl; return 0; }
2 最长公共子序列
#include <stdio.h> #include <iostream> #include <string.h> #define MAXLEN 100 void LCSLength(char *x, char *y, int m, int n, int c[][MAXLEN], int b[][MAXLEN]) { int i, j; for(i = 0; i <= m; i++) c[i][0] = 0; for(j = 1; j <= n; j++) c[0][j] = 0; for(i = 1; i<= m; i++) { for(j = 1; j <= n; j++) { if(x[i-1] == y[j-1]) { c[i][j] = c[i-1][j-1] + 1; b[i][j] = 0; } else if(c[i-1][j] >= c[i][j-1]) { c[i][j] = c[i-1][j]; b[i][j] = 1; } else { c[i][j] = c[i][j-1]; b[i][j] = -1; } } } } void PrintLCS(int b[][MAXLEN], char *x, int i, int j) { if(i == 0 || j == 0) return; if(b[i][j] == 0) { PrintLCS(b, x, i-1, j-1); printf("%c ", x[i-1]); } else if(b[i][j] == 1) PrintLCS(b, x, i-1, j); else PrintLCS(b, x, i, j-1); } int main(int argc, char **argv) { char x[MAXLEN] = "ABCBDAB"; char y[MAXLEN] = "BDCABAB"; int b[MAXLEN][MAXLEN]; int c[MAXLEN][MAXLEN]; int m, n; m = strlen(x); n = strlen(y); LCSLength(x, y, m, n, c, b); PrintLCS(b, x, m, n); return 0; }
本博客内容均来自网络,如有雷同,是我抄袭!