開啟章節選單

10903 Rock-Paper-Scissors Tournament

題目連結

提醒

此題名稱於官網標註為「Playing War」,經團隊研判可能為誤植,此頁面題解為經過團隊修正之內容。

題目敘述

兩位玩家玩剪刀石頭布遊戲:

  • 剪刀贏布

  • 布贏石頭

  • 石頭贏剪刀

出相同手勢為平手(不算勝也不算負)

現在有 n 位玩家,每對玩家要玩 k 次比賽。你的任務是計算每位玩家的「勝率」,公式如下: win / (win + lose) 平手不算進去,若某玩家完全沒有勝場或敗場(即沒參與非平手比賽 win + lose = 0),則輸出 -。

輸入格式

多組測資,第一行 n, k 接下來 k _ n _ (n - 1) / 2 行,每行分別為兩個玩家與玩家手勢。

輸出格式

對於每組測資,輸出 n 行,每行一位玩家的勝率(小數點後三位),或 - (若勝率無法計算)。

每組測資間 輸出一個空白行,但最後一組不可以多輸出空白行。

解題思路

模擬比賽:

  • 為每位玩家紀錄勝場與敗場。

  • 遇到平手不計入任何人戰績。

用函式決定勝負:

  • 比較兩個手勢,回傳誰贏誰輸(可用 pair<int, int>)

勝率計算與輸出:

  • 若 (win + lose) == 0 則輸出 -

  • 否則輸出 win / (win + lose),格式化輸出到小數點後三位

格式處理:

  • 每組測資間空一行,最後一組不多空行

程式碼

#include <bits/stdc++.h>
using namespace std;

pair<int, int> who_win(string a, string b, int pa, int pb) {
  if (a == b) return {0, 0};
  if ((a == "rock" && b == "scissors") || (a == "scissors" && b == "paper") ||
      (a == "paper" && b == "rock")) {
    return {pa, pb};
  } else {
    return {pb, pa};
  }
}

int main() {
  int n, k;
  bool first_case = true;

  while (cin >> n >> k && n) {
    if (!first_case) cout << "\n";
    first_case = false;

    int win[101] = {0}, lose[101] = {0};
    string m1, m2;
    int p1, p2;
    int total_games = k * n * (n - 1) / 2;

    for (int i = 0; i < total_games; ++i) {
      cin >> p1 >> m1 >> p2 >> m2;
      auto result = who_win(m1, m2, p1, p2);
      if (result.first != 0) {
        win[result.first]++;
        lose[result.second]++;
      }
    }

    for (int i = 1; i <= n; i++) {
      if (win[i] + lose[i] == 0) {
        cout << "-\n";
      } else {
        double rate = (double)win[i] / (win[i] + lose[i]);
        cout << fixed << setprecision(3) << rate << "\n";
      }
    }
  }

  return 0;
}