动态规划难度相对较大。它的基础是最优原理。有很多问题,用贪婪法或者分而治之无法简洁高效的解决,但是动态规划就可以。
在动态规划中,我们要考察一系列抉择,以确定一个最优抉择序列是否包含最优抉择子序列。当最优抉择包含最优抉择子序列时,可建立动态规划递归方程以帮助我们高效解决问题。
动态规划常常基于一个递推式或一个或多个初始状态。当前子问题的解将由上一个子问题的解推出。一般是多项式复杂度。
1.0/1背包问题
有n个物品和一个容量为c的背包,从n个物品中选取装包的物品。物品i的重量为wi,价值为pi。一个可行的背包装载是指,背包的物品总重量不超过背包的容量。一个最佳的背包装载是物品总价值最高的可行的背包装载。
问题的公式描述是 maxΣpixi ; 约束条件是 Σwixi <= c且 xi∈{0,1}.
1)递归求解,F(1,c)返回f(1,c)的值。
int F(int i, int y)
{//Return f(i,y).
if(i == n) return (y < w[n]) ? 0 : p[n];
if(y < w[i]) return F(i+1,y);
return max(F(i+1,y),F(i+1,y-w[i])+p[i]);
}
2)迭代计算 f 和 x
template<class T>
void Knapsack(T p[], int w[], int c, int n, T** f){
//Compute f[i][y] for all i and y.
//initialize f[n][]
for(int y = 0; y < w[n]; y++)
f[n][y] = 0;
for(int y = w[n]; y <= c; y++)
f[n][y] = p[n];
//compute remaining f's
for(int i = n - 1; i > 1; i--){
for(int y = 0; y < w[i]; y++)
f[i][y] = f[i+1][y];
for (int y = w[i]; y <=