Круговой алгоритм Турнира в C#

Быть Хорошим Программистом действительно требует работы в нескольких аспектах поля: Разработка приложений, Системы (Ядро) работа, Дизайн Пользовательского интерфейса, База данных, и так далее. Существуют определенные подходы, характерные для всех и определенных подходов, которые характерны для одного аспекта задания. Необходимо изучить, как программировать Java как кодер Java, не как кодер C++ и наоборот. Дизайн Пользовательского интерфейса действительно труден, и использует другую часть Вашего мозга, чем кодирование, но реализация, что UI в коде является еще одним навыком также. Это не просто, что нет "одного" подхода к кодированию, но нет всего одного типа кодирования.

7
задан Matt 28 May 2012 в 15:15
поделиться

4 ответа

Это должно быть достаточно легко сделать, используя модульную арифметику:

ОБНОВЛЕНИЕ 2: (как и обещал правильный алгоритм)

public void ListMatches(List<string> ListTeam)
{
    if (ListTeam.Count % 2 != 0)
    {
        ListTeam.Add("Bye");
    }

    int numDays = (numTeams - 1);
    int halfSize = numTeams / 2;

    List<string> teams = new List<string>();

    teams.AddRange(ListTeam.Skip(halfSize).Take(halfSize));
    teams.AddRange(ListTeam.Skip(1).Take(halfSize -1).ToArray().Reverse());

    int teamsSize = teams.Count;

    for (int day = 0; day < numDays; day++)
    {
        Console.WriteLine("Day {0}", (day + 1));

        int teamIdx = day % teamsSize;

        Console.WriteLine("{0} vs {1}", teams[teamIdx], ListTeam[0]);

        for (int idx = 1; idx < halfSize; idx++)
        {               
            int firstTeam = (day + idx) % teamsSize;
            int secondTeam = (day  + teamsSize - idx) % teamsSize;
            Console.WriteLine("{0} vs {1}", teams[firstTeam], teams[secondTeam]);
        }
    }
}

, который будет печатать каждый день командные матчи.

Позвольте мне быстро объяснить, как работает алгоритм:

Я заметил, что, поскольку мы меняем все команды, кроме первой, если мы помещаем все команды в массив, кроме первой, то мы должны просто считайте первую команду из этого массива, используя смещение индекса в зависимости от дня и выполняя модульную арифметику для правильного перехода. На практике мы будем рассматривать этот массив как бесконечно повторяющийся в обоих направлениях, и мы будем постепенно сдвигать наш обзор вправо (или влево).

Однако есть одна загвоздка, и это факт, что мы должны упорядочьте команды особым образом, чтобы это работало правильно. В противном случае мы не получим правильного вращения. Из-за этого нам также нужно очень своеобразно читать подходящую вторую команду.

Правильный способ подготовить свой список следующий:

  • Никогда не помещайте в список первую команду (Команда №1).
  • Возьмите последнюю половину списка команд и поместите ее в начало списка.
  • Возьмите первую половину списка, переверните его и поместите в список (но не в группу № 1).

Теперь правильный способ чтения списка следующий:

  • Для каждого дня увеличивайте первый индекс, который вы просматриваете, на ] 1 .
  • Для первой команды, которую вы видите в этом месте, сопоставьте эту команду с Командой № 1.
  • Для следующей команды в списке ( (день + idx)% numDays ), мы обычно сопоставляем его с командой, которая компенсируется половиной количества команд минус 1 (минус 1, потому что мы сами имели дело с первым матчем). Однако, поскольку вторая половина нашего списка была подготовлена ​​путем возврата, нам нужно сопоставить это смещение во второй половине списка с возвратом. Более простой способ сделать это - заметить, что это эквивалентно сопоставлению того же индекса, но с конца списка. Учитывая текущее смещение дней , то есть (day + (numDays - idx))% numDays .

ОБНОВЛЕНИЕ 3: Я не был счастлив, что мое решение включало такие запутанные выбор, сопоставление, реверсирование элементов массива. После того, как я задумался о своем решении, я понял, что слишком озабочен соблюдением заданного порядка команд. Однако это не является обязательным требованием, и можно получить другое, но одинаково действующее расписание, не заботясь о первоначальном заказе. Все, что имеет значение, - это алгоритм выбора, который я описываю во второй части моего объяснения.

Таким образом, вы можете упростить следующие строки:

teams.AddRange(ListTeam.Skip(halfSize).Take(halfSize));
teams.AddRange(ListTeam.Skip(1).Take(halfSize -1).ToArray().Reverse());

до:

teams.AddRange(ListTeam); // Copy all the elements.
teams.RemoveAt(0); // To exclude the first team.
11
ответ дан 6 December 2019 в 09:20
поделиться

Похоже, вы хотите запланировать круговой турнир . Статья wp содержит алгоритм.

Я не понимаю, где вы даже пытаетесь повернуть массив. Перестановка будет выглядеть примерно так: 1 -> 2 -> 3 -> 4 ... -> n / 2 - 1 -> n - 1 -> n - 2 -> n - 3 -> ... -> n / 2 -> 1 (и 0 остается неизменным). Можно сделать это в 2 петли (верхний ряд и нижний ряд).

6
ответ дан 6 December 2019 в 09:20
поделиться

Это может быть запутанный метод, но его можно свести к проблеме теории графов. Создайте вершину графа для каждой команды и создайте ребро между каждой вершиной (чтобы получился полный граф). Затем для алгоритма:

Для каждого дня i = 1 .. n:

  • Выберите любые две неотмеченные вершины, которые напрямую соединены, и пометьте ребро между ними i. Отметьте обе вершины.
  • Повторяйте, пока не будут отмечены все вершины.
  • Выведите помеченные ребра (например, team1 vs team2, team3 vs team4 и т. Д.)
  • Удалите помеченные ребра из графа и сбросьте все вершины на неотмеченные.
1
ответ дан 6 December 2019 в 09:20
поделиться

Как насчет вычисления возможных комбинаций для каждого дня, который вы хотите, а затем

  1. отсортировать их в каждой паре, т.е. команда с наименьшим номером всегда первая в любой паре.
  2. отсортируйте перечисленные пары для каждого дня по первому в каждом пара.
0
ответ дан 6 December 2019 в 09:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: