ラウンドロビンを試してください。これは、プロセス間でタイムスロットを共有するための単純なスケジューリングアルゴリズムですが、この問題はどういうわけか私にそれを思い出させます。
編集
これがラウンドロビントーナメントの実装です。ODDのチーム数がある場合は、ダミーチームを挿入する必要があります。そうしないと、対戦相手のいないチームが存在します。ラウンド数は偶数なので、合計ラウンド数は(NumberOfTeams-1)です。最初に、最初のラウンドを設定しました。
ABCDEFGH
HGFEDCBA
つまり、チームA-H、チームB-Gなどです。
これからは、たとえばAなどの1つのチームを固定します。次に、A_Sideチームを2番目の位置から右にシフトします。最後のチームはポジション2になります(ABCDEFGHはAHBCDEFGになります)。(楽しみのために)rotate_A_side()再帰メソッドを参照してください。
B_Sidesの半分が左にシフトされます。これにより、HGFED-GFEDになります。
チームの選択は対称的であるため(AはHでプレイし、次にHはAでプレイします)、B_Sideの上半分はA_Sideの下位チームの逆コピーです。したがって、DCBAはCBHAになります)。rotate_B_side()を参照してください。
したがって、ラウンド2は次のとおりです。
HBCDEFG _
GFED CBHA
すべてのラウンドを行うには、前述のシフト手順を繰り返すだけです。NextRound()を参照してください
アルゴリズムを実装するac#クラスは次のとおりです。
class Teams
{
private int[] A_Side;
private int[] B_Side;
public int[,] PlayingCounter;
public int RoundCounter = 1;
public bool DummyTeam = false; // ODD number of teams -> one team will no be able to play.
public bool NextRoundExists
{
get
{
return (RoundCounter < B_Side.Length-1);
}
}
public Teams(int NumberOfTeams)
{
if (NumberOfTeams % 2 != 0)
{
NumberOfTeams++; DummyTeam = true;
}
A_Side = new int[NumberOfTeams];
B_Side = new int[NumberOfTeams];
PlayingCounter = new int[NumberOfTeams,NumberOfTeams]; // Counting to see if alg is correct
int x,y;
for (x=0; x<NumberOfTeams; x++)
{
A_Side[x] = x + 1;
B_Side[NumberOfTeams-x-1]=x+1;
for (y=0;y<NumberOfTeams;y++)
{
PlayingCounter[x,y] = 0;
}
}
}
private void rotate_A_Side(int AtPos)
{
if (AtPos == 1)
{
int iO = A_Side[A_Side.Length - 1];
rotate_A_Side(AtPos+1);
A_Side[1] = iO;
}
else
{
if (AtPos < A_Side.Length - 1) { rotate_A_Side(AtPos + 1); }
A_Side[AtPos] = A_Side[AtPos - 1];
}
}
public void rotate_B_Side()
{
int i;
for (i = 0; i<B_Side.Length/2 ; i++)
{
B_Side[i] = B_Side[i + 1];
}
for (i = B_Side.Length / 2; i < B_Side.Length; i++)
{
B_Side[i] = A_Side[B_Side.Length/2 - (i -B_Side.Length/2 + 1) ];
}
}
public bool NextRound()
{
if (NextRoundExists)
{
RoundCounter++; // Next round
rotate_A_Side(1); // A side rotation
rotate_B_Side(); // B side rotation
LogRound(); // Update counters
return true;
}
else return false;
}
public void LogRound()
{
for (int x = 0; x < A_Side.Length; x++)
{
PlayingCounter[A_Side[x]-1, B_Side[x]-1]++;
PlayingCounter[B_Side[x]-1, A_Side[x]-1]++;
}
}
public string GetCounters()
{
string return_value = "";
for (int y = 0; y < A_Side.Length; y++)
{
for (int x = 0; x < A_Side.Length; x++)
{
return_value += String.Format(" {0:D3}", PlayingCounter[y, x]);
}
return_value += System.Environment.NewLine;
}
return return_value;
}
public string GetCurrentRound()
{
string Round = "Round #" + RoundCounter.ToString() + " ";
for (int x = 0; x < B_Side.Length; x++)
{
Round += String.Format("Team {0} - Team {1};", A_Side[x], B_Side[x]);
}
return Round;
}
}
コードから、次のように使用できます。
Teams Rounds = new Teams(22);
if (Rounds.DummyTeam) {
// Anything to do if nober of teams is odd?
}
Rounds.LogRound(); // DEBUG - you can check number of matches ;-)
while (Rounds.NextRoundExists) // While we have next round...
{
Rounds.NextRound(); // ... generate the next
// round (team assignment)
// Your can tack using: Rounds.GetCurrentRound()
}
// If you want to see the number of matches, call Rounds.GetCounters();
6チームから次の出力が得られました。
ラウンド#1 AF; なれ ; CD ; DC; EB; FA;
ラウンド#2 AE; FD; 紀元前; CB; DF; EA;
ラウンド#3 AD; EC; FB; BF; CE; DA;
ラウンド#4 AC; DB; EF; FE; BD; CA;
ラウンド#5 AB; CF; DE; ED; FC; BA;
チーム1をAなどに置き換えました。
rotate_B_Side()を改良する必要があります。これは簡単なアプローチです。