ホームページ >バックエンド開発 >PHPチュートリアル >PHPのアルゴリズムについて教えてください。
フットボール リーグ用のアルゴリズムを作成する必要があります。
要件は非常に簡単です
A1 A2 A3 A4 A5 A6
1 ラウンドに 1 試合がある場合
第 1 ラウンド
A1VSA2 A3VSA4 A5VSA6
第 3 ラウンド
..
各チームは、ホーム 5 試合とアウェイ 5 試合を含む、他の 5 チームと 10 試合を行います (彼は前後にいます)
そのようなアルゴリズムにはうんざりします
結局、私たちは次のようなアルゴリズムに従わなければなりません1ラウンドに対して、ユーザーが2ラウンド目を選択できる場合、2ラウンド目で誰と誰が得点したかが一覧表示されます!
ディスカッション(解決策)への返信
まず、半数の3チームをホームゲームに指定し、残りの3チームで循環させます。
次に、逆にしてもう一度実行します。
ホーム チームとアウェイ チームがあり、同時に試合が 2 つのチーム間で行われることを考えると、一方のチームはホームで、もう一方のチームはアウェイでなければなりません。指定されるなら、こんな感じでできると思います
まず半分の3チームをホームゲームと決めて、残りの3チームを巡回します。
次に、逆にしてもう一度実行します。
$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 -- A6A2 -- A5A3 -- A4== 2 ==A6 -- A4A5 -- A3A1 -- A2== 3 ==A2 -- A6A3 -- A1A4 -- A5== 4 ==A6 -- A5A1 -- A4A2 -- A3== 5 ==A3 -- A6A4 -- A2A5 -- A1これは単一ループです 二重ループは 14 行の
while($lun++ < $len-1) {
を
while($lun++ < ($len-1)*2) {
に変更しますただそれだけです
バーガーにそのようなアレンジメントを思いつくのは本当に難しいです
アルゴリズムを修正するのに5、6時間かかりました
たとえば、初日は、A1-A2 A3-A4 A5-A6
つまり、各チームは対戦相手と 2 試合あります
ただし、1 回はホーム、もう 1 回はアウェイです。
もちろん、そんなに単純ではありません。そうしないと、大会組織委員会が気を緩めすぎてしまいます
ダブルラウンドロビンの配置方法も探しましたが、残念ながら見つかりませんでした。
そこでテストを行ったところ、シングルループのアルゴリズムをダブルループに拡張できることがわかりました。成功の確率は 10,000 分の 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を必須にすることができます
見に来てください!
投稿者の質問はとても興味深いので、フォーム記入ゲームをしましょう! 6 チームあると仮定します。1 試合だけが行われ、チーム数の小さいチームがホームコートを占有することになります。
アウェイでプレーするつもりですか?チーム番号の大きい方をホームでプレーさせてください!
ホームとアウェイでそれぞれ 5 試合ずつ、10 試合が行われますか?前の手順で作成した 2 つのテーブルを 5 回コピーします。
そんなに単純なのは何か問題があるはずです
現在、世界中のすべてのシングルラウンドロビントーナメントは「バーガーアレンジメント方式」を採用しています。 』で紹介したものです。もちろん、「左回り回転法」も使えますが、若干問題はありますが、アルゴリズムはもっと簡単です
ダブルラウンドロビンの配置方法も探しましたが、残念ながら見つかりませんでした。
そこでテストを行ったところ、シングルループのアルゴリズムをダブルループに拡張できることがわかりました。成功確率は 10,000 分の 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を要求するには、2 番目の単一サイクルの初期シーケンスは次のいずれかである必要があります
投稿者の質問はとても興味深いので、フォーム記入ゲームをしましょう! 6 チームあると仮定します。1 試合だけが行われ、チーム数の小さいチームがホームコートを占有することになります。
アウェイでプレーするつもりですか?チーム番号の大きい方をホームでプレーさせてください!
ホームとアウェイでそれぞれ 5 試合ずつ、10 試合が行われますか?前の手順で作成した 2 つのテーブルを 5 回コピーします。
こんなに単純なのに何か問題があるはずです
答えはすでに示しています
参加チームの順序を変更するだけです
そんな些細なことでいつも悩むのは無意味です
$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 -- A6A2 -- A5A3 -- A4== 2 ==A6 -- A4A5 -- A3A1 -- A2== 3 ==A2 -- A6A3 -- A1A4 -- A5== 4 ==A6 -- A5A1 -- A4A2 -- A3== 5 ==A3 -- A6A4 -- A2A5 -- A1これは単一ループです
アルゴリズムはソフトウェアの魂です