在上一篇文章里,我对参加荣光医院医道会的比赛策略进行了分析,在这篇文章里重点说明一些相关的算法。
首先是把符合A+B+C=100这个条件的所有组合列出来,算法如下:
for i=100 to 0 step -1
for j = 100 to 0 step -1 if (i + j <= 100) then for k = 100 to 0 step -1 if (i + j + k = 100) then row = dw_data.insertRow(0) dw_data.setItem(row, "jiancha", i) dw_data.setItem(row, "yituo", j) dw_data.setItem(row, "zhuanjia", k) end if next end if next next |
算法的核心思想是使用三重循环,分别代表A、B、C,然后将符合A+B+C=100这个条件的所有组合保存起来。我用的是PowerBuilder编写的代码,红色部分就是数据输出,如果你用其它的语言编写,对上面代码进行相应的改造即可。
第二个算法就是用上面计算出来的5151种组合,分别与保存的对手组合历史记录进行比较,得到获胜最多次数的组合。实现这个算法有很多种方法,我采用的是数据库计算方法,首先确定两个数据库:
组合列表数据库,保存全部5151种可能组合,表名称:rongList,字段:id, jiancha, yituo, zhuanjia。
对手组合历史记录数据库,保存每天对手所出的组合,表名称:rongHistory,字段:id, jiancha, yituo, zhuanjia。
使用一条SQL语句计算每种组合的胜率:
select c.jiancha, c.yituo, c.zhuanjia, d.num, d.id, e.total, (d.num / e.total)
from rongList c, (select count(*) as num, b.id as id from rongHistory a, rongList b where (a.jiancha < b.jiancha and a.yituo < b.yituo) or (a.jiancha < b.jiancha and a.zhuanjia < b.zhuanjia) or (a.yituo < b.yituo and a.zhuanjia < b.zhuanjia) group by b.id) d, (select count(*) as total from rongHistory) e where c.id = d.id order by d.num desc; |
其中红色代码是最核心的部分,它计算出了对于保存下来的历史记录,所有5151种组合中,每一种组合获胜的次数。在输出结果部分,c.jiancha, c.yituo, c.zhuanjia 分别对应A、B、C,d.num就是获胜次数,e.total就是历史记录数量,(d.num / e.total) 就是胜率。关于这条语句的更加详细的解释,嗯,如果你懂得SQL语言,我没必要解释,因为你一看就明白了,如果你不懂,我也没必要解释,因为说了你也不明白,你只要知道使用这句话,可以达到计算出胜率的目的就好了。
整个算法采用了SQL语句来实现,只有一句,显得代码非常优雅,效率非常高,可移植性非常好。
如果用其他语言实现,譬如C、JAVA、Delphi、VB等,都免不了使用双重循环一一计算每个组合获胜的次数,代码量上就多了很多,从语句的数量上来说多的就更多了,因为毕竟上面的代码只是一条语句而已。
在执行的效率上,随着历史记录的增加,使用其他语言编写的算法无一例外的会陷入效率越来越低的状况,而且无法改善,而这种集合运算,正是数据库的强项,数据量的增加对于运算效率影响没那么明显,况且还可以通过增加索引等手段大幅度提高运算效率。
可移植性就更不用说了,SQL语言是标准的数据库语言,基本上所有的数据库都支持,上面的这一句代码,可以不用修改就运行在任意数据库上,从简单的桌面数据库,到复杂的商业数据库,统统没问题,嗯,实在是爽。
本文转自 tywali 51CTO博客,原文链接:http://blog.51cto.com/lancelot/301920,如需转载请自行联系原作者