您的位置:首页 > 其它

动态规划

2008-12-08 14:13 134 查看
动态规划是,据说,最难的一类算法。确实,看起来也是非常的费劲;很多内容没看太明白,先总结一部分,然后再说吧。

[概念]

1,和贪婪算法一样,在动态规划中,可将一个问题的解决方案视为一系列决策的结果。不同的是,在贪婪算法中,每采用一次贪婪准则便做出一个不可撤回的决策,而在动态规划中,还要考察每个最优决策序列中是否包含一个最优子序列。

2,当最优决策序列中包含最优决策子序列时,可建立动态规划递归方程(recurrence equation),它可以帮助我们高效地解决问题。根据我的理解,这个递归方程是整个动态规划问题的核心:如果可以制作递归方程,那么基本上就是可解的;如果不能构造出递归方程,则很难对这个问题实施可行性的解。

3,动态规划方法采用最优原则( principle of optimality)来建立用于计算最优解的递归式。所谓最优原则即不管前面的策略如何,此后的决策必须是基于当前状态(由上一次决策产生)的最优决策。由于对于有些问题的某些递归式来说并不一定能保证最优原则,因此在求解问题时有必要对它进行验证。若不能保持最优原则,则不可应用动态规划方法。在得到最优解的递归式之后,需要执行回溯以构造最优解。

4,使用递归程序来求解动态规划递归方程的时候,如果不避免重复计算,递归程序的复杂性将非常恐怖。所以,希望能够在递归程序设计中解决重复计算,或者使用迭代方式来求解,自然地避免了重复计算。如果没有了重复计算,复杂性将急剧下降。尽管迭代程序与避免重复计算的递归程序有相同的复杂性,但迭代程序不需要附加的递归栈空间,因此将比避免重复计算的递归程序更快。

[具体案例]

1,最短路经

a, 有向图,要寻找一条从源节点s= 1到目的节点d= 5的最短路径,即选择此路径所经过的各个节点。

b, 解释:最短路径问题中,假如在第一次决策时到达了某个节点v,那么不管v 是怎样确定的,此后选择从v 到d 的路径时,都必须采用最优策略。

2,0/1背包问题

a, 如前所述,在该问题中需要决定x1 .. xn的值。假设按i = 1,2,.,n 的次序来确定xi 的值。如果置x1 = 0,则问题转变为相对于其余物品(即物品2,3,.,n),背包容量仍为c 的背包问题。若置x1 = 1,问题就变为关于最大背包容量为c-w1 的问题。现设r={c,c-w1 } 为剩余的背包容量。

b, 解释:在这个问题中,第i个元素的值的选择(0或者1),不会影响后续n-i个元素的解;另外,刨除i之后,后面n-i个元素的最优解,必定是构成整个解的最优解的一部分。

c, 递归方程:

f(n,y) = p(n), if y>=w(n);

or = 0, if y<w(n);

f(i,y)= max(f(i+1, y), f(i+1,y-w(i)) + p(i), if y>=w(i);

or = f(i+1,y), if y<w(i);

根据这个递归方程,很容易就能构造出来一个递归的代码(没有验证和调试):

int f(int i, int j)

{

if (i == n) return (y < w
) ? 0 : p
;

if (y < w
) return f(i+1, y);

return max(f(i+1,y), f(i+1, y-w[i]) + p[i]);

}

3,航费

4,图像压缩

5,所有点对的最短路径

6,矩阵乘法链

a, 一个m×n矩阵A与n×p矩阵B相乘需耗费O(m*n*p)的时间。(A*B) *C和A* (B*C) ,尽管这两种不同的计算顺序所得的结果相同,但时间消耗会有很大的差距。

b, 使用动态规划的方法,会期望把性能降低到O(q^3),q是矩阵个数。

c, 递归方程:

c(i,i) = 0 --> 1<=i<=q; c保存的是费用;

c(i, i+1)=r[i]*r[i+1]*r[i+2], 同时, kay(i, i+1) = i; --> 1<=i<=q;

c(i, i+s) = min(c(i, k) + c(k+1, i+s) + r[i]*r[k+1]*r[i+s+1], --> 1<=i<=q-s, 1<s<q; k属于[i, i+s)累计

kay(i,j)保存的事从i到j中能够得到最小K的数据;

[矩阵乘法链代码]

const int SIZE = 6;

// matrix row and cols

int r[SIZE] = {10, 5, 1, 10, 2, 10};

// matrix mult order

int kay[SIZE][SIZE] = {0};

// avoid re-computing for cost

int c[SIZE][SIZE] = {0};

// calculate the min cost of:

// M(i,k) X M(k,j)

int cost(int i, int j)

{

if ( c[i][j] > 0) //avoid re-computing for cost

return c[i][j];

if (i == j) // M(ii) need no time

return 0;

if (i == (j - 1)) { // M(i,i) X M(i+1,i+1) need: r(i)*r(i+1)*r(i+2)

kay[i][j] = i;

return c[i][j] = r[i]*r[i+1]*r[j+1];

}

// more than 2 matrices for mult

// set min u

int u = cost(i, i) + cost(i + 1, j) + r[i]*r[i+1]*r[j+1];

kay[i][j] = i;

// compute the remain min term

for ( int k = i + 1; k < j; k++) {

int temp = cost(i, k) + cost(k + 1, j) + r[i]*r[k+1]*r[j+1];

if ( temp < u ) {

u = temp;

kay[i][j] = k;

}

}

c[i][j] = u;

return u;

}

// print result

void printResult(int i, int j)

{

if ( i == j )

return;

printResult(i, kay[i][j]);

printResult(kay[i][j] + 1, j);

printf("Multiply M[%d,%d]", i, kay[i][j]);

printf(" and M[%d,%d]/n", kay[i][j] + 1, j);

}

// test

int main(int argc, char* argv[])

{

cost(0, SIZE - 2);

printResult(0, SIZE - 2);

getchar();

return 0;

}

[其他]

待扩展
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: