动态规划是用来解决“最优”问题,通过找到最优的子策略来解决这个问题
解决方法
递归:从结果出发,指导终止条件
递推:按顺序进行,但可以保存阶段状态
与分治法的区别:
(分治法的步骤:
分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;
解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题
合并:将各个子问题的解合并为原问题的解。
例子:汉诺塔
)
在递归过程中,动态规划就是分治法中多了了比较
例子:
0-1背包问题的实现
=============================== 递推 ===================================
#define OBJ_COUNT 4
#define TOTAL_WEIGHT 4
int main() {
cout << " 0,1 bage" << endl; // prints !!!Hello World!!!
// 1st dimension, obj index
// 2nd dimension, 1:weight; 2: value
int objs[OBJ_COUNT][2] = { {1,2}, {2,4} , {3,6}, {1,3} ,};
int v[OBJ_COUNT][TOTAL_WEIGHT+1];
for(int i=0; i < OBJ_COUNT; i++)
for (int j=1; j<= TOTAL_WEIGHT; j++ )
v[i][j] = 0;
v[0][objs[0][0]] = objs[0][1]; // input the 1st obj
for ( int i=1; i < OBJ_COUNT; i++) {
for( int j=1; j<= TOTAL_WEIGHT; j++ ) {
//cout << "objs[i][0]:" << objs[i][0] << " j:" << j <<endl;
if ( objs[i][0] > j)
v[i][j] = v[i-1][j]; //no update, because weight too large
else if ( objs[i][0] == j)
v[i][j] = v[i-1][j] < objs[i][1]? objs[i][1]: v[i-1][j]; // 看同权值的总重为 j 的是否权值较小, 取最大权值
else {
int correspondIndex = j - objs[i][0]; //取去掉当前 obj 的总量,
int newWeight = v[i-1][correspondIndex] + objs[i][1]; // 重新计算
if ( newWeight > v[i-1][j]) //取最大权值
v[i][j] = newWeight;
}
}
}
cout << "w: ";
for (int j=1; j<= TOTAL_WEIGHT; j++ )
cout << j << " ";
cout << endl;
for ( int i=0; i < OBJ_COUNT; i++){
cout << i<<": ";
for (int j=1; j<= TOTAL_WEIGHT; j++ )
cout << v[i][j] << " ";
cout << endl;
}
return 0;
}
=============================== 递归 ===================================
#define OBJ_COUNT 4
#define TOTAL_WEIGHT 4
int objs[OBJ_COUNT+1][2] = { {0,0}, {1,2}, {2,4} , {3,6}, {1,3} ,};
int F(int n, int v) {
if ( n==0 )
return 0;
else {
if ( objs[n][0] > v ) {
return F( n-1, v);
}
else {
int a = F( n-1, v);
int b = F( n-1, v-objs[n][0] ) + objs[n][1];
return a>b? a: b;
}
}
}
int main() {
cout << " 0,1 bage" << endl;
cout << F(OBJ_COUNT,TOTAL_WEIGHT);
}