+ -
当前位置:首页 → 问答吧 → 从X个球中取Y个球,统计各和值出现次数,寻找高手优化算法

从X个球中取Y个球,统计各和值出现次数,寻找高手优化算法

时间:2010-09-17

来源:互联网

需求:从X个球中取出Y个球为一组,计算该组球的和值,统计各个和值的出现次数,球号从1号开始,一组球中的各号码是不重复的。还不明白请去看北京快乐8的彩票玩法。
 
下面是我写的一个实现,这个算法是通过列出每一种可能,然后对得出的每组号码计算和值,再统计各和值的出现次数。代码如下:
复制代码
  1.  <?php
  2. /*
  3.  * 计算球的和值
  4.  */
  5. function sum_balls($balls){
  6.  $sum = 0;
  7.  foreach ($balls as $a)
  8.   $sum += (int)$a;
  9.  return $sum;
  10. }
  11. /*
  12.  * 格式化$balls
  13.  */
  14. function format_balls($balls){
  15.  $str = "";
  16.  foreach ($balls as $ball){  
  17.   $str = $str.($ball < 10 ? "0".$ball : $ball)." ";
  18.  }
  19.  return $str;
  20. }
  21. /*
  22.  * 从$total_ball_num个球中选出$select_ball_num个球,计算各和值出现的次数
  23.  */
  24. function calc_keno_sum_times($total_ball_num, $select_ball_num){
  25.  if($total_ball_num <= 0 || $select_ball_num <= 0 ||
  26.   $select_ball_num > $total_ball_num || $total_ball_num > 99){
  27.   echo "你输入的数字不符合要求,程序退出...";
  28.   exit;
  29.  }
  30.  
  31.  $min_sum = ($select_ball_num + 1) * $select_ball_num / 2; //最小和值,高斯算法
  32.  $max_sum = $min_sum + ($total_ball_num - $select_ball_num) * $select_ball_num;//最大和值
  33.  echo "最小和值:${min_sum},最大和值:${max_sum}<br />";
  34.  $result = array();//保存和值次数的结果
  35.  
  36.  //初始化$result数组中的元素,后面就不需要再判断是否存在该元素了
  37.  for($i = $min_sum; $i <= $max_sum; $i++){
  38.   $result[$i] = 0;
  39.  }
  40.  
  41.  $ball_sum = 0;
  42.  $balls = initBalls($select_ball_num);
  43.  
  44.  
  45.  echo "从{$total_ball_num}个球中选择{$select_ball_num}个球,各组合如下:<br />";
  46.  while($balls != null){
  47.   $ball_sum = sum_balls($balls);
  48.   $result[$ball_sum]++;
  49.   echo format_balls($balls)." ".$ball_sum."<br />";
  50.   $balls = getNextBalls($total_ball_num, $select_ball_num, $balls);
  51.  }
  52.   
  53.  return $result; 
  54. }
  55. /*
  56.  * 初始化第一组号码
  57.  */
  58. function initBalls($select_ball_num){
  59.  $balls = array();
  60.  for($i = 1; $i <= $select_ball_num; $i++){//balls下标从1开始
  61.   $balls[$i] = $i;
  62.  }
  63.  return $balls;
  64. }
  65. /*
  66.  * 获得下一组号码,如果已经是最后一组号码,则返回null
  67.  */
  68. function getNextBalls($total_ball_num, $select_ball_num, $balls){
  69.  $i = $select_ball_num;
  70.  while($i >= 1){
  71.   if(++$balls[$i] <= ($total_ball_num - $select_ball_num + $i)){
  72.    //小于或等于该位置允许的最大值时,中断循环
  73.    break;
  74.   } else {
  75.    $i--;
  76.   }
  77.  }
  78.  if($i >= 1){
  79.   //每个后面的球等于前面的球加1
  80.   while((++$i) <= $select_ball_num){
  81.    $balls[$i] = $balls[$i-1] + 1;
  82.   }
  83.  } else {
  84.   //已经没有其它组合了
  85.   return null;
  86.  }
  87.  
  88.  return $balls;
  89. }
  90. /*
  91.  * 计算指定范围内和值数
  92.  */
  93. function calc_range_sum($result, $min, $max){
  94.  $count = 0;
  95.  for($i = $min; $i <= $max; $i++){
  96.   $count += $result[$i];
  97.  }
  98.  return $count;
  99. }
  100. /*
  101.  * 输出 结果
  102.  */
  103. function print_result($result){
  104.  echo "各和值情况如下:<br />";
  105.  foreach ($result as $key => $value){
  106.   echo $key."\t".$value."<br />";
  107.  }
  108. }
  109. $result = calc_keno_sum_times(20, 7);
  110. print_result($result);
  111. ?>


这个算法要是计算的球数较少,倒没感觉有什么问题,当数值比较大的时候,就会变得很慢,比如从80个球中选20个,跑了两小时还没统计出来。希望有高手能够给出其它算法。
 
以前一直用Java,刚学PHP,因此就用PHP来写了(一边查手册一边写的),权当练手,代码写的不好,请指教,勿喷,谢谢。

作者: peacesoft   发布时间: 2010-09-17

我看啦下 你用的最多应该是循环啊
尽量减少循环 ,等有空在帮你看看,主要对那个游戏不清楚啊

作者: lbc227540   发布时间: 2010-09-17

相关阅读 更多

热门下载

更多