ホームページ >バックエンド開発 >PHPチュートリアル >PHPのアルゴリズムについて教えてください。

PHPのアルゴリズムについて教えてください。

WBOY
WBOYオリジナル
2016-06-23 13:51:451393ブラウズ

フットボール リーグ用のアルゴリズムを作成する必要があります。
要件は非常に簡単です
A1 A2 A3 A4 A5 A6
1 ラウンドに 1 試合がある場合
第 1 ラウンド
A1VSA2 A3VSA4 A5VSA6
第 3 ラウンド
..

各チームは、ホーム 5 試合とアウェイ 5 試合を含む、他の 5 チームと 10 試合を行います (彼は前後にいます)

そのようなアルゴリズムにはうんざりします

結局、私たちは次のようなアルゴリズムに従わなければなりません1ラウンドに対して、ユーザーが2ラウンド目を選択できる場合、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 ラウンドは、A2-A1 A4-A3 A6-A5 になる可能性があります

つまり、各チームは対戦相手と 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 であることがわかります。
2 番目の単一サイクルの初期シーケンスは次のいずれかである必要があり、
    [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 回コピーします。

こんなに単純なのに何か問題があるはずです



重要なのは、チームが 12 ある場合、アルゴリズムを書くのはより難しいということです

答えはすでに示しています
参加チームの順序を変更するだけです
そんな些細なことでいつも悩むのは無意味です

$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
これは単一ループです
二重ループは
while($lun++ < $len-1) {
を次のように変更します
while($lun++ < ($len-1)*2) {
以上です

バーガーにそのような配置を思いつくのは本当に難しいです
アルゴリズムを修正するのに 5 ~ 6 時間かかりました


笑、悪くない、非常に忍耐強い。
しばらくいじってみたら、たまたま忙しかったので、それ以上勉強しませんでした。

アルゴリズムはソフトウェアの魂です

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。