- 注册时间
- 2007-12-27
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 2608
- 在线时间
- 小时
|
发表于 2012-3-29 14:43:35
|
显示全部楼层
-
- da[s_] := Module[{n = Length[s]}, Append[Rest[s] Range[n - 1], 0] + s Range[n - 1, 0, -1]];
- rr[s_] := Prepend[Most[s], 0];
- gg[k_, n_, s0_] := Module[{s = Table[0, {n}], ds, i}, If[k == 0, Return[Append[Table[0, {n}], 1]]];
- Do[ds = da[s0[[k - i + 1]]] Binomial[n - 1 - k + i, i - 1]; If[i == 1, ds = rr[ds];]; s += ds;, {i, k}];
- If[k < n, Do[ds = s0[[k - i + 1]] Binomial[n - 1 - k + i, i]; If[i == 0, ds = rr[ds];]; s += ds;, {i, 0, k}]];
- Append[s, 0]];
- m = 30;
- s1 = {{0, 0, 1}, {0, 2, 0}, {1, 0, 0}}; ss = {{1, 0}}; n = 2;
- Do[n++; s0 = s1; s1 = Table[gg[i, n, s0], {i, 0, n}]; AppendTo[ss, Most[Last[s1]]];, {m - 2}]; // Timing
- sk = Map[#/Apply[Plus, #] &, ss]; // Timing
- ans = {0, 1}; Do[AppendTo[ans, ans.sk[[k]]];, {k, m - 1}]; // Timing
- ans // ListPlot
复制代码 把代码贴出来吧。
的确是分2步,其中sk就是第2步的输入(例如:用{1, 0}表示2人射击后剩余0人和1人的几率, {1/4, 3/4, 0}表示3人射击后剩余0、1、2人的几率),ans的那行去做10层说的工作。ss是用状态数表示的sk(例如:{1, 0}对应2人时共有1种射击方式的分布,{2, 6, 0}对应3人时所有的8种射击方式的分布),看,初始时n=2,只有一个ss为{1, 0}。
对于要计算ss的第1步,主要由gg来实现,gg[k,n]表示有n个人时,其中k个人开枪(其余人不开枪)的状态结果(s0参数只是为了递推存数使的),我们想要的ss就是gg[n,n]。看,初始时s1 = {{0, 0, 1}, {0, 2, 0}, {1, 0, 0}},分别表示gg[0,2],gg[1,2]和gg[2,2]。可以看到,4个gg[0-3,3]都是可以用这3个已知的gg[0-2,2]来算出的,然后就递推吧。这个算法求的是精确值,如果改为数值计算或许效率更高些。
计算结果在0.5上下震荡,还是比较有趣的。 |
|