1. 程式人生 > 其它 >1018 錘子剪刀布 (20 分)

1018 錘子剪刀布 (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

    k2;k2勝k1的條件是(k2+1)%3 ==k1

    在得到該局的輸贏之後,對甲乙的勝、平、負次數進行操作,並對贏得該局的一方的手勢次數加一

  • 比較得到勝利次數最多的手勢,輸出需要的資訊

  • 注意點:

    1. 由於scanf使用%c時會將換行符\n讀入,因此需要在合適的地方用getchar吸收空格,否則會導致讀入與題意不符。
    2. 甲贏的時候同時要記乙負,乙贏甲負,這是成對出現的。

參考程式碼

#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; 
}