1018 錘子剪刀布 (20 分)
阿新 • • 發佈:2021-07-20
1018 錘子剪刀布 (20 分)
大家應該都會玩“錘子剪刀布”的遊戲:兩人同時給出手勢,勝負規則如圖所示:
現給出兩人的交鋒記錄,請統計雙方的勝、平、負次數,並且給出雙方分別出什麼手勢的勝算最大。
輸入格式:
輸入第 1 行給出正整數 N(≤105),即雙方交鋒的次數。隨後 N 行,每行給出一次交鋒的資訊,即甲、乙雙方同時給出的的手勢。C
代表“錘子”、J
代表“剪刀”、B
代表“布”,第 1 個字母代表甲方,第 2 個代表乙方,中間有 1 個空格。#
輸出格式:
輸出第 1、2 行分別給出甲、乙的勝、平、負次數,數字間以 1 個空格分隔。第 3 行給出兩個字母,分別代表甲、乙獲勝次數最多的手勢,中間有 1 個空格。如果解不唯一,則輸出按字母序最小的解。//字典序就是按字典拍的字母順序
輸入樣例:
10
C J
J B
C B
B B
B C
C C
C B
J B
B C
J J
輸出樣例:
5 3 2
2 3 5
B B
思路
考慮到最後要輸出字典序的最小的解,將三種手勢按字典序排序,即B(布)、C(石頭)、J(剪刀)。可以發現,這個順序又恰好是迴圈相剋的順序,即B勝C,C勝J,J勝B,將BCJ對應位0、1、2,作為一維陣列mp的三個元素,mp[0]='B'、mp[1]='C'、mp[2]='J';同時寫一個函式change(char c)來將手勢對應到數字
對每組讀入的甲乙手勢c1和c2,先將其通過change函式準換為數字k1和k2,然後判斷該局輸贏。由於設定的順序恰好就是迴圈相剋順序,因此k1勝k2的條件是(k1+1)%3k2,而k1和k2平的條件是k1
在得到該局的輸贏之後,對甲乙的勝、平、負次數進行操作,並對贏得該局的一方的手勢次數加一
比較得到勝利次數最多的手勢,輸出需要的資訊
注意點:
- 由於scanf使用%c時會將換行符\n讀入,因此需要在合適的地方用getchar吸收空格,否則會導致讀入與題意不符。
- 甲贏的時候同時要記乙負,乙贏甲負,這是成對出現的。
參考程式碼
#include<stdio.h> int change(char c){//字元轉變數字的方法,定義個int型別的返回函式 if(c == 'B') return 0; if(c == 'C') return 1; if(c == 'J') return 2; } int main(){ int n; char mp[3] = {'B', 'C', 'J'};//字元與0, 1, 2一一對應 scanf("%d", &n); char c1, c2; int k1, k2; int hand_A[3] = {0}, hand_B[3] = {0}; int v1 = 0, v2 = 0, f1 = 0, f2 = 0, p = 0; for(int i = 0; i < n; i++){ getchar(); scanf("%c %c", &c1, &c2); k1 = change(c1);//轉換為數字 k2 = change(c2); if((k1 + 1) % 3 == k2){ v1++;//這裡的v1v2其實都可以用陣列來記錄,會更加方便,f1和f2同理 f2++; hand_A[k1]++; }else if(k1 == k2){ p++; }else{ v2++; f1++; hand_B[k2]++; } } printf("%d %d %d\n", v1, p, f1); printf("%d %d %d\n", v2, p, f2); int id1 = 0, id2 = 0; for(int i = 0; i < 3; i++){ if(hand_A[i] > hand_A[id1]) id1 = i;//id1表示最大的手勢,如果有比他大的,就更像id1 if(hand_B[i] > hand_B[id2]) id2 = i; //這裡就算有多個解,但是i是從小到大的,當不等式兩把相等的時候,並不會進行後面的句子,所以還是可以去到最小的解 } printf("%c %c\n", mp[id1], mp[id2]); //轉變回BCJ return 0; }