求PHP算法 求大神帮助

whwdgjlcl 2014-08-09 09:18:26
我有一个需求 写一个 足球联赛的 算法。
需求是这样的 很简单 有六只球队
A1 A2 A3 A4 A5 A6
然后 如果一轮一场比赛的话
第一论
A1VSA2 A3VSA4 A5VSA6
第二轮
A1VSA4 A2VSA5 A3VSA6
第三轮
....

每个球队都会跟 其他五个球队比赛10次 其中 主场5次 客场5次 (他在前和 在后)

这么个算法 愁死我了

最后就要 按照 一轮一场 如 让用户选择 第二轮 就会 列出 第二轮 谁和谁的比分来!

...全文
339 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
李睿_Lee 2014-08-11
  • 打赏
  • 举报
回复
引用 4 楼 xuzuning 的回复:
$a = array('A1', 'A2', 'A3', 'A4', 'A5', 'A6');

berger_method($a);

function berger_method($ar) {
  if(count($ar) %2) $ar[] = ' ';
  $t = array_merge(range(1, count($ar)-1), range(1, count($ar)-1));

  $len = count($ar);
  $m = range(1, $len);
  $lun = 0;
  $last = 0;
  $k = $len <= 4 ? 1 : ($len - 4) / 2 + 1;
  while($lun++ < $len-1) {
    $s = array_values($m);
    echo "== $lun ==\n";
    for($i=0; $i<$len/2; $i++) printf("%s -- %s\n", $ar[$s[$i]-1], $ar[$s[$len-1-$i]-1]);
    echo "\n";

    list($m[0], $m[$len-1]) = array($m[$len-1], $m[0]);
    for($i=0; $i<$k; $i++) {
      if($m[++$last % $len] == $len) $last++;
    }
    $n = $last %= $len;
    for($i=1; $i<$len; $i++) {
      if(($m[$n]) == $len) $n = ($n + 1) % $len;
      $m[$n] = $i;
      $n = ($n + 1) % $len;
    }
  }
}
== 1 ==
A1 -- A6
A2 -- A5
A3 -- A4

== 2 ==
A6 -- A4
A5 -- A3
A1 -- A2

== 3 ==
A2 -- A6
A3 -- A1
A4 -- A5

== 4 ==
A6 -- A5
A1 -- A4
A2 -- A3

== 5 ==
A3 -- A6
A4 -- A2
A5 -- A1
这是单循环的 双循环将 14 行的 while($lun++ < $len-1) { 改作 while($lun++ < ($len-1)*2) { 就可以了 真难为了 贝格尔 弄出这么个编排法 绕了5、6个小时才把算法理顺
哈哈,不错,挺有耐心的。 我折腾了下,发现没那么简单,正好也忙,就没再去研究了。
xuzuning 2014-08-11
  • 打赏
  • 举报
回复
答案我已经给你了 只要在下一个但循环的时候变化一下参赛队的次序就可以了 总纠结这种小事的没有意义的
whwdgjlcl 2014-08-11
  • 打赏
  • 举报
回复
引用 10 楼 wander_wind 的回复:
楼主的问题太有趣了,让我们来玩个填表游戏吧!我假设固定6只球队,只打一场且队伍号码小的占主场! 要打客场?让队号大的打主场就OK! 要打10场,主客各5场?把上一步的2个表复制5遍! 这么简单肯定有问题
关键是 如果 球队是12个呢 是个活的 算法比较难写
whwdgjlcl 2014-08-11
  • 打赏
  • 举报
回复
引用 7 楼 xuzuning 的回复:
当然不是那么简单,否则赛事组委会也太轻松了 目前世界性单循环赛都采用“贝格尔编排方法”,就是我介绍的这种。当然你也可以采用“逆时针轮转方法”,虽然存在一些问题,但算法要简单的多 我也搜索了双循环赛的编排方法,但遗憾的是无法找到。 于是我做了一下测试,结果发现把单循环的算法推广到双循环时。成功的概率只有万分之36,这也就是都不愿公开双循环编排方法的原因吧。
$a = array('A1', 'A2', 'A3', 'A4', 'A5', 'A6');
$last = berger_method($a);

set_time_limit(60);
$x = 10000;
$double = array();
do {
  shuffle($a);
  $r = array_merge($last, berger_method($a));
  $res = array_combine($a, array_fill(0, count($a), array('场数' => 0, '主场' => 0, '客场' => 0)));

  foreach($r as $item) {
    $res[$item['主场']]['场数']++;
    $res[$item['主场']]['主场']++;
    $res[$item['客场']]['场数']++;
    $res[$item['客场']]['客场']++;
  }
  if(! array_filter($res, function($v) { return $v['主场'] != $v['客场']; })) {
    $double[] = join(',', $a);
  }
}while($x--);
print_r(array_values(array_unique($double)));
可知,当初始序列为 A1,A2,A3,A4,A5,A6 时 第二个单循环的初始序列必须为下列之一时,才能要求
    [0] => A4,A5,A6,A2,A3,A1
    [1] => A5,A6,A4,A1,A2,A3
    [2] => A5,A4,A6,A3,A2,A1
    [3] => A4,A6,A5,A3,A1,A2
    [4] => A5,A6,A4,A2,A3,A1
    [5] => A6,A5,A4,A1,A2,A3
    [6] => A6,A5,A4,A1,A3,A2
    [7] => A6,A4,A5,A1,A2,A3
    [8] => A4,A6,A5,A2,A3,A1
    [9] => A5,A4,A6,A2,A3,A1
    [10] => A6,A5,A4,A2,A1,A3
    [11] => A5,A4,A6,A1,A2,A3
    [12] => A4,A6,A5,A2,A1,A3
    [13] => A4,A5,A6,A1,A2,A3
    [14] => A6,A5,A4,A3,A2,A1
    [15] => A5,A4,A6,A1,A3,A2
    [16] => A6,A5,A4,A3,A1,A2
    [17] => A4,A5,A6,A3,A2,A1
    [18] => A6,A4,A5,A2,A1,A3
    [19] => A4,A5,A6,A2,A1,A3
    [20] => A5,A6,A4,A2,A1,A3
    [21] => A6,A4,A5,A3,A2,A1
    [22] => A5,A6,A4,A3,A1,A2
    [23] => A4,A6,A5,A1,A2,A3
    [24] => A5,A6,A4,A3,A2,A1
    [25] => A4,A6,A5,A1,A3,A2
    [26] => A6,A4,A5,A2,A3,A1
    [27] => A5,A4,A6,A2,A1,A3
    [28] => A4,A6,A5,A3,A2,A1
    [29] => A4,A5,A6,A3,A1,A2
    [30] => A5,A4,A6,A3,A1,A2
    [31] => A6,A4,A5,A3,A1,A2
    [32] => A6,A4,A5,A1,A3,A2
    [33] => A5,A6,A4,A1,A3,A2
    [34] => A6,A5,A4,A2,A3,A1
    [35] => A4,A5,A6,A1,A3,A2
嗯 但是 我感觉 将赛场 反算 可能就对了 但是 可能也有问题! 我还在测试!
智商众筹 2014-08-11
  • 打赏
  • 举报
回复
楼主的问题太有趣了,让我们来玩个填表游戏吧!我假设固定6只球队,只打一场且队伍号码小的占主场!











要打客场?让队号大的打主场就OK!
要打10场,主客各5场?把上一步的2个表复制5遍!

这么简单肯定有问题
兰亭倒序 2014-08-11
  • 打赏
  • 举报
回复
来看看!
傲雪星枫 2014-08-11
  • 打赏
  • 举报
回复
關注一下。
xuzuning 2014-08-11
  • 打赏
  • 举报
回复
当然不是那么简单,否则赛事组委会也太轻松了 目前世界性单循环赛都采用“贝格尔编排方法”,就是我介绍的这种。当然你也可以采用“逆时针轮转方法”,虽然存在一些问题,但算法要简单的多 我也搜索了双循环赛的编排方法,但遗憾的是无法找到。 于是我做了一下测试,结果发现把单循环的算法推广到双循环时。成功的概率只有万分之36,这也就是都不愿公开双循环编排方法的原因吧。
$a = array('A1', 'A2', 'A3', 'A4', 'A5', 'A6');
$last = berger_method($a);

set_time_limit(60);
$x = 10000;
$double = array();
do {
  shuffle($a);
  $r = array_merge($last, berger_method($a));
  $res = array_combine($a, array_fill(0, count($a), array('场数' => 0, '主场' => 0, '客场' => 0)));

  foreach($r as $item) {
    $res[$item['主场']]['场数']++;
    $res[$item['主场']]['主场']++;
    $res[$item['客场']]['场数']++;
    $res[$item['客场']]['客场']++;
  }
  if(! array_filter($res, function($v) { return $v['主场'] != $v['客场']; })) {
    $double[] = join(',', $a);
  }
}while($x--);
print_r(array_values(array_unique($double)));
可知,当初始序列为 A1,A2,A3,A4,A5,A6 时 第二个单循环的初始序列必须为下列之一时,才能要求
    [0] => A4,A5,A6,A2,A3,A1
    [1] => A5,A6,A4,A1,A2,A3
    [2] => A5,A4,A6,A3,A2,A1
    [3] => A4,A6,A5,A3,A1,A2
    [4] => A5,A6,A4,A2,A3,A1
    [5] => A6,A5,A4,A1,A2,A3
    [6] => A6,A5,A4,A1,A3,A2
    [7] => A6,A4,A5,A1,A2,A3
    [8] => A4,A6,A5,A2,A3,A1
    [9] => A5,A4,A6,A2,A3,A1
    [10] => A6,A5,A4,A2,A1,A3
    [11] => A5,A4,A6,A1,A2,A3
    [12] => A4,A6,A5,A2,A1,A3
    [13] => A4,A5,A6,A1,A2,A3
    [14] => A6,A5,A4,A3,A2,A1
    [15] => A5,A4,A6,A1,A3,A2
    [16] => A6,A5,A4,A3,A1,A2
    [17] => A4,A5,A6,A3,A2,A1
    [18] => A6,A4,A5,A2,A1,A3
    [19] => A4,A5,A6,A2,A1,A3
    [20] => A5,A6,A4,A2,A1,A3
    [21] => A6,A4,A5,A3,A2,A1
    [22] => A5,A6,A4,A3,A1,A2
    [23] => A4,A6,A5,A1,A2,A3
    [24] => A5,A6,A4,A3,A2,A1
    [25] => A4,A6,A5,A1,A3,A2
    [26] => A6,A4,A5,A2,A3,A1
    [27] => A5,A4,A6,A2,A1,A3
    [28] => A4,A6,A5,A3,A2,A1
    [29] => A4,A5,A6,A3,A1,A2
    [30] => A5,A4,A6,A3,A1,A2
    [31] => A6,A4,A5,A3,A1,A2
    [32] => A6,A4,A5,A1,A3,A2
    [33] => A5,A6,A4,A1,A3,A2
    [34] => A6,A5,A4,A2,A3,A1
    [35] => A4,A5,A6,A1,A3,A2
「已注销」 2014-08-11
  • 打赏
  • 举报
回复
算法才是软件的灵魂呀
whwdgjlcl 2014-08-11
  • 打赏
  • 举报
回复
比如 第一天 A1-A2 A3-A4 A5-A6 第二轮 可能是A2-A1 A4-A3 A6-A5 就是每个队 跟对手 都有两场比赛 但是 主场一次 客场一次!
whwdgjlcl 2014-08-11
  • 打赏
  • 举报
回复
引用 4 楼 xuzuning 的回复:
$a = array('A1', 'A2', 'A3', 'A4', 'A5', 'A6');

berger_method($a);

function berger_method($ar) {
if(count($ar) %2) $ar[] = ' ';
$t = array_merge(range(1, count($ar)-1), range(1, count($ar)-1));

$len = count($ar);
$m = range(1, $len);
$lun = 0;
$last = 0;
$k = $len <= 4 ? 1 : ($len - 4) / 2 + 1;
while($lun++ < $len-1) {
$s = array_values($m);
echo "== $lun ==\n";
for($i=0; $i<$len/2; $i++) printf("%s -- %s\n", $ar[$s[$i]-1], $ar[$s[$len-1-$i]-1]);
echo "\n";

list($m[0], $m[$len-1]) = array($m[$len-1], $m[0]);
for($i=0; $i<$k; $i++) {
if($m[++$last % $len] == $len) $last++;
}
$n = $last %= $len;
for($i=1; $i<$len; $i++) {
if(($m[$n]) == $len) $n = ($n + 1) % $len;
$m[$n] = $i;
$n = ($n + 1) % $len;
}
}
}
== 1 ==
A1 -- A6
A2 -- A5
A3 -- A4

== 2 ==
A6 -- A4
A5 -- A3
A1 -- A2

== 3 ==
A2 -- A6
A3 -- A1
A4 -- A5

== 4 ==
A6 -- A5
A1 -- A4
A2 -- A3

== 5 ==
A3 -- A6
A4 -- A2
A5 -- A1
这是单循环的
双循环将 14 行的
while($lun++ < $len-1) {
改作
while($lun++ < ($len-1)*2) {
就可以了

真难为了 贝格尔 弄出这么个编排法
绕了5、6个小时才把算法理顺




非常感谢 版主大人 版主果然厉害! 但是 还有有问题的 版主 求救啊!晚上 都睡不着 因为这个算法。



是这样的 选择一天一场 然后 根据 参赛队伍 出现总轮数

然后一天一场的 意思 是 每个球队 每天 一场比赛

比赛都是分 主场和客场的
您这个 只是每个队 又一场比赛 比如 A1 -- A6 这是 主场:客场 但是没有 反过来的 A6 VS A1
这个 好像不只是 反过来 那么简单!

xuzuning 2014-08-10
  • 打赏
  • 举报
回复
$a = array('A1', 'A2', 'A3', 'A4', 'A5', 'A6');

berger_method($a);

function berger_method($ar) {
  if(count($ar) %2) $ar[] = ' ';
  $t = array_merge(range(1, count($ar)-1), range(1, count($ar)-1));

  $len = count($ar);
  $m = range(1, $len);
  $lun = 0;
  $last = 0;
  $k = $len <= 4 ? 1 : ($len - 4) / 2 + 1;
  while($lun++ < $len-1) {
    $s = array_values($m);
    echo "== $lun ==\n";
    for($i=0; $i<$len/2; $i++) printf("%s -- %s\n", $ar[$s[$i]-1], $ar[$s[$len-1-$i]-1]);
    echo "\n";

    list($m[0], $m[$len-1]) = array($m[$len-1], $m[0]);
    for($i=0; $i<$k; $i++) {
      if($m[++$last % $len] == $len) $last++;
    }
    $n = $last %= $len;
    for($i=1; $i<$len; $i++) {
      if(($m[$n]) == $len) $n = ($n + 1) % $len;
      $m[$n] = $i;
      $n = ($n + 1) % $len;
    }
  }
}
== 1 ==
A1 -- A6
A2 -- A5
A3 -- A4

== 2 ==
A6 -- A4
A5 -- A3
A1 -- A2

== 3 ==
A2 -- A6
A3 -- A1
A4 -- A5

== 4 ==
A6 -- A5
A1 -- A4
A2 -- A3

== 5 ==
A3 -- A6
A4 -- A2
A5 -- A1
这是单循环的 双循环将 14 行的 while($lun++ < $len-1) { 改作 while($lun++ < ($len-1)*2) { 就可以了 真难为了 贝格尔 弄出这么个编排法 绕了5、6个小时才把算法理顺
whwdgjlcl 2014-08-10
  • 打赏
  • 举报
回复
你好 不是那么简单的!求解!
李睿_Lee 2014-08-10
  • 打赏
  • 举报
回复
引用 1 楼 Novolee 的回复:
这是循环赛还是什么么?忘了怎么称呼了。排赛是抽签呢?还是直接指定? 鉴于有主场和客场,同时,比赛是两队之间的,一队是主场,另一队必定是客场。如果是指定的话,我觉得可以这样来: 先定一半球队即其中三个球队为主场,跟剩下的三队循环一下。 然后反一下,再来一次。
不对,好像搞错了,想太简单了。。。 囧。。。
李睿_Lee 2014-08-10
  • 打赏
  • 举报
回复
这是循环赛还是什么么?忘了怎么称呼了。排赛是抽签呢?还是直接指定? 鉴于有主场和客场,同时,比赛是两队之间的,一队是主场,另一队必定是客场。如果是指定的话,我觉得可以这样来: 先定一半球队即其中三个球队为主场,跟剩下的三队循环一下。 然后反一下,再来一次。
更新日志- XISE已经很久没有再更新,感谢大家的支持 现将内部XISE-WBMS V8.86免费放出 自带23套模版 新增一句话可过安全狗,使用时请将杀软关闭使用。 新概念网站后台远程多功能管理系统——XISE 网站后台管理系统 已支持PHP、ASP、ASPX、JSP四种语言 ,文章将持续更新。请关注开发进程。软件只供学习参考,如用于非法用途与本软件作者无关! 软件全部功能总结: 可视化操作,支持PHP、ASP、ASPX、JSP语言环境 多线程线程池操作,API编写,字节集读取,winhttpAPI访问,真正达到毫秒级反应 更适合新手使用,不仅有可视界面,并带有一键返回网站根目录,让你完全掌握自身方位 支持在4种语言的SHELL内自动生成内页 自动识别服务器编码,自动转码 更适合SEO,模板秒收录秒排名,模板标签功能齐全,能模仿所有SHELL页面 多站多任务模式 目录霸占,无法用其它工具打开 动态JS代码替换 采集还原覆盖劫持 更具有安全性,防脱壳、防注入后门、密码屏蔽、加密,大大增加了软件使用的安全性 支持SHELL收录量、BR、PR、快照时间多线程批量查询并保存 真正及时同步百度算法优化,只要百度算法更新,第二天软件就更新 支持多线程状态查询,查询正确率高达99% 支持批量多线程删除上传下载,弥补旧菜刀无法批量操作的遗憾 使用API查看超大文件,弥补了打开大文件时直接崩溃 一键写入脚本代码,快速清马 一键修改文件属性、时间、名称 一键随机写入或植入被控端并保存到数据库 一键多选复制目录的URL地址 超人性化设置,控件细节操作堪比大团队定制,win8界面,职业级清晰控件排版,新手上手直接变大神 超智能判断,设置键相比其他软件少了80%,功能却比其它软件强大10倍 智能的记录数据,急速百万条记录读取,百万级SHELL轻松管理 点击图片即可查看,无需下载 支持批量的导入与导出 更多功能细节请查看历史更新记录

21,882

社区成员

发帖
与我相关
我的任务
社区描述
从PHP安装配置,PHP入门,PHP基础到PHP应用
社区管理员
  • 基础编程社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧