Mathematica动态规划算法,虽然不是我想要的路径算法T.T...但确实是好东西
原文地址:[转载]用Mathematica写动态规划程序
作者:Elisa
http://blog.dccmx.com/2011/09/dynamic-programming-in-mathematica/
最近系统莫名挂了,重装的时候整理了一下那些几百年没碰的文件。发现了一堆几年前写的Mathematica程序。悲剧的是:很多都看不懂了,当时是用这玩意来学习数学和函数式编程的。
挑了个有点意思的程序来复习一下。
问题是这样的:
有1, 2, 5, 10, 20, 50, 100, 200面值的钞票。用这些钞票(不限量),有多少种方法凑出200来(比如:1张200、2张100等)。
这种问题最优雅的解法就是动态规划。
Mathematica中提供了一些语法来方便我们写动态规划程序。
1.“/;”:用来表示规则成立的条件。例如可以这样定义绝对值函数:
1
2
3
4
5
6
|
In
[13]:= abs[x_] /; x < 0 := -x;
abs[x_] /; x >= 0 := x;
In
[15]:= {abs[1], abs[0], abs[-1]}
Out
[15]= {1, 0, 1}
|
2.记住函数结果(动态规划精髓),即当可以将函数运算的结果存起了,下次用相同参数调用统一函数的时候,不需要重复计算,直接返回结果。语法是这样的:
1
|
f[x_, y_] := f[x, y] = x + y;
|
当第一次调用f[1,2]时,Mathematica将计算一次加法。第二次再调用f[1,2]时,直接返回3.
于是,上面的问题可以这样解决:
1
2
3
4
5
6
7
8
9
10
|
value = {1, 2, 5, 10, 20, 50, 100, 200};
Clear
[NumberOfWay];
(*此处用于清除已保存的NumberOfWay[v_,n_],因为对于不同的value,这个值是不一样的*)
NumberOfWay[v_, n_] /; v > 0 && n > 0 :=
NumberOfWay[v, n] =
Sum
[
NumberOfWay[v - i value[[n]], n - 1],
{i, 0, v/value[[n]]}
];
NumberOfWay[v_, 0] /; v > 0 := 0;
NumberOfWay[0, n_] /; n >= 0 = 1;
|
1
2
|
$RecursionLimit =
Infinity
;
NumberOfWay[200, 8]
|
Mathematica真乃神器也!