10903. Турнир гора – бумага - ножницы

 

Игра гора – ножницы - бумага ведется двумя игроками A и B. Каждый из игроков независимо друг от друга выбирает гору, ножницы или бумагу. Бумага выигрывает у горы, ножницы выигрывают у бумаги, гора выигрывает у ножниц.

Проводится турнир среди n игроков, в котором каждый участник играет с каждым по k игр. Итого проводится k * n * (n – 1) / 2 игр. Для каждого игрока следует найти средний выигрыш. Он равен w / (w + l), где w – число выигранных игр, l – число проигранных.

 

Вход. Первая строка каждого теста содержит количество игроков n (1 £ n £ 100) и количество проведенных каждым участником игр k (1 £ k £ 100). Далее следуют игры, каждая их которых имеет формат p1, m1, p2, m2 (1 £ p1, p2 £ n). Здесь p1, p2 – номера игроков, m1, m2 – их выбор. Последняя строка содержит единственный ноль и не обрабатывается.

 

Выход. Для каждого игрока в каждом тесте вывести его средний выигрыш с тремя точками после запятой. Если средний выигрыш неопределен, то вывести ‘-‘. Выходные данные тестов разделять пустой строкой.

 

Пример входа

2 4

1 rock 2 paper

1 scissors 2 paper

1 rock 2 rock

2 rock 1 scissors

2 1

1 rock 2 paper

0

 

Пример выхода

0.333

0.667

 

0.000

1.000

 

 

РЕШЕНИЕ

моделирование

 

Анализ алгоритма

Для каждого теста следует промоделировать игру, запоминая количество выигрышей и проигрышей каждого игрока. Далее для каждого игрока вывести значение w / (w + l), где w – число его выигранных игр, l – число проигранных. Если для некоторого игрока значение w + l равно 0, то выводим ‘-‘.

 

Пример

В первом примере проведено 4 игры, три из которых результативны (не являются ничьими). Первый игрок выиграл 1 раз, проиграл 2 раза. Средний выигрыш первого игрока составляет 1 / (1 + 2) = 0.333.

 

Реализация алгоритма

В символьные массивы m1 и m2 считываем исходы текущей игры: гора, ножницы или бумага. players[i][1] содержит число выигранных игр i – ым игроком, а players[i][0] – число проигранных.

 

char m1[10], m2[10];

int players[MAX][2];

 

Функция wins возвращает -1, если текущая игра заканчивается ничьей. Ничья возможна лишь в том случае, когда оба игрока выбрали одинаковый исход. Функция wins возвращает 1, если исход, находящийся в m1, побеждает исход, находящийся в m2. Иначе возвращается 0.

Проверку исхода можно совершать, не сравнивая его целиком со словом, а лишь проверяя его первую букву. Например, массив m1 содержит исход «rock» тогда и только тогда, когда m1[0] = ‘r’.

 

int wins(void)

{

  if (((m1[0] == 'p') && (m2[0] == 'p')) ||

      ((m1[0] == 'r') && (m2[0] == 'r')) ||

      ((m1[0] == 's') && (m2[0] == 's'))) return -1;

  if (((m1[0] == 'p') && (m2[0] == 'r')) ||

      ((m1[0] == 'r') && (m2[0] == 's')) ||

      ((m1[0] == 's') && (m2[0] == 'p'))) return 1;

  return 0;

}

 

Основной цикл программы. Читаем входные значения n, k. Обнуляем массив players – изначально каждый игрок имеет 0 выигрышей и 0 проигрышей.

 

scanf("%d %d",&n,&k);

do{

  memset(players,0,sizeof(players));

 

Читаем данные k*n*(n – 1)/2 игр. Увеличиваем на единицу players[i][1], если в игре побеждает i - ый игрок, и players[i][1], если i - ый игрок проигрывает.

 

  for(i = 0; i < k*n*(n-1)/2; i++)

  {

    scanf("%d %s %d %s\n",&p1,m1,&p2,m2);

    if ((res = wins()) == -1) continue;

    if (res) {players[p1][1]++; players[p2][0]++;}

      else {players[p2][1]++; players[p1][0]++;}

  }

 

Выводим средний выигрыш для каждого игрока. Если игрок не имеет выигрышей и проигрышей (а имеет только ничьи), то его средний выигрыш определить невозможно, в таком случае выводим ‘-‘.

 

  for(i = 1; i <= n; i++)

    if (!(players[i][0] + players[i][1])) printf("-\n");

    else

       printf("%.3lf\n",1.0*players[i][1] / (players[i][0] + players[i][1]));

 

Между тестами следует выводить пустую строку. После вывода результатов на последний тест печатать пустую строку не следует.

 

  scanf("%d %d",&n,&k);

  if (n) printf("\n");

} while(n);