首页  编辑  

循环赛(日程安排)

Tags: /超级猛料/Alogrith.算法和数据结构/乱七八糟/   Date Created:

循环赛(日程安排)

Michael Gillson

 摘 要:如何建立任意大小的循环赛程安排?

 关键字:动态数组 循环赛

 类 别:其它

--------------------------------------------------------------------------------

通过使用Delphi动态数组,数组大小不是在设计时而是在运行时确定的。

此处是用于建立循环赛程安排的单元,

unit uSupport;

interface

const

 BYE_GAME : Integer = -1;

type

 TPair = Record

   Home : Integer;

   Away : Integer;

   Round : Integer;

   Desc : String;

 End;

 TPairings = Array of TPair;

procedure MakeSchedule (var Pairings : TPairings; iTeams : Integer);

implementation

procedure MakeSchedule (var Pairings : TPairings; iTeams : Integer);

var

 bAddedBye : Boolean;

 iGamesPerRound : Integer;

 iRounds : Integer;

 Teams : Array of Integer;

 I,J : Integer;

 iRound : Integer;

 iTeam : Integer;

 iGame : Integer;

 iTotalGames : Integer;

 iPair : Integer;

 iLastTeam : Integer;

 iSaveTeam : Integer;

 Pair : TPair;

begin

 {

   防止低级错误

 }

 If iTeams < 2 Then

   Exit;

 {

是否每次都有一场轮空?

 }

 If iTeams Mod 2 = 0 Then

   bAddedBye := False

 Else

 Begin

   bAddedBye := True;

   iTeams := iTeams + 1;

 End;

 iRounds := iTeams - 1;

 iGamesPerRound := iTeams Div 2;

 {

确定比赛总场数

 }

 iTotalGames := iRounds * iGamesPerRound;

 SetLength (Pairings,iTotalGames);

 {

为除第一队外的所有队伍建立数组。

 }

 SetLength (Teams,iTeams - 1);

 iTeam := 1;

 iLastTeam := iTeams - 2;

 For I := 0 To iLastTeam Do

 Begin

   iTeam := iTeam + 1;

   If bAddedBye And (iTeam = iTeams) Then

     Teams [I] := BYE_GAME

   Else

     Teams [I] := iTeam;

 End;

 {

按逆时针方向使队伍循环。第一队保持不变。下面的例子示范10支队伍的情形。

   1-10 1-9 1-8 1-7 1-6 1-5 1-4 1-3 1-2

   2-9 10-8 9-7 8-6 7-5 6-4 5-3 4-2 3-10

   3-8 2-7 10-6 9-5 8-4 7-3 6-2 5-10 4-9

   4-7 3-6 2-5 10-4 9-3 8-2 7-10 6-9 5-8

   5-6 4-5 3-4 2-3 10-2 9-10 8-9 7-8 6-7

处于第一位的是主队。因为第一队总是主队,所以我会交换那支队伍。我通常在表中把轮空当成是一支客队。

 }

 iPair := 0;

 For iRound := 1 To iRounds Do

 Begin

   iTeam := 0;

   For iGame := 1 To iGamesPerRound Do

   Begin

     With Pairings [iPair] Do

     Begin

       Round := iRound;

       Desc := '';

       If iTeam = 0 Then

         {

      把第一队换成主场,强行使轮空当成是客队。

         }

         If (iRound Mod 2 = 0) And (Teams [iLastTeam] > 0) Then

         Begin

           Home := Teams [iLastTeam];

           Away := 1;

         End

         Else

         Begin

           Home := 1;

           Away := Teams [iLastTeam];

         End

       Else

       {

         保证轮空是客队。

       }

         If Teams [iTeam - 1] > 0 Then

         Begin

           Home := Teams [iTeam - 1];

           Away := Teams [iLastTeam - iTeam];

         End

         Else

         Begin

           Home := Teams [iLastTeam - iTeam];

           Away := Teams [iTeam - 1];

         End;

     End;

     iTeam := iTeam + 1;

     iPair := iPair + 1;

   End;

   {

     使队伍循环

   }

   iSaveTeam := Teams [iLastTeam];

   For I := iLastTeam DownTo 1 Do

     Teams [I] := Teams [I - 1];

   Teams [0] := iSaveTeam;

 End;

 {

用浮泡排序法把最低的主队放在前面。

 }

 For I := 0 To iTotalGames - 1 Do

   For J := I + 1 To iTotalGames - 1 Do

     If (Pairings [J].Round = Pairings [I].Round) And

        (Pairings [J].Home < Pairings [I].Home) Then

     Begin

       Pair := Pairings [J];

       Pairings [J] := Pairings [I];

       Pairings [I] := Pair;

     End;

end;

end.

这里给出打印循环赛程的简易方法。

procedure TfrmMain.btnMakeScheduleClick(Sender: TObject);

var

 Pairings : TPairings;

 I,J : Integer;

 iRounds : Integer;

begin

 RichEdit1.Clear;

 iRounds := StrToIntDef (edtRounds.Text,2);

 MakeSchedule (Pairings,iRounds);

 J := 0;

 For I := Low (Pairings) To High (Pairings) Do

 Begin

   {

     另一轮比赛

   }

   If Pairings [I].Round <> J Then

   Begin

     J := Pairings [I].Round;

     RichEdit1.Lines.Add ('Round ' + IntToStr (J));

   End;

   If Pairings [I].Away < 1 Then

     RichEdit1.Lines.Add (' Home : ' + IntToStr (Pairings [I].Home) + ' Away : BYE')

   Else

     RichEdit1.Lines.Add (' Home : ' + IntToStr (Pairings [I].Home) + ' Away : ' +

                          IntToStr (Pairings [I].Away));

 End;

end;