1018-锤子剪刀布
题目要求如下:
输入格式: 输入第 1 行给出正整数 N(≤105),即双方交锋的次数。随后 N 行,每行给出一次交锋的信息,即甲、乙双方同时给出的的手势。C 代表“锤子”、J 代表“剪刀”、B 代表“布”,第 1 个字母代表甲方,第 2 个代表乙方,中间有 1 个空格。 输出格式: 输出第 1、2 行分别给出甲、乙的胜、平、负次数,数字间以 1 个空格分隔。第 3 行给出两个字母,分别代表甲、乙获胜次数最多的手势,中间有 1 个空格。如果解不唯一,则输出按字母序最小的解。
思路:
只需将问题分解,通过每种获胜情况进行计数,并比较大小给出输出即可,但要注意,测试点中有0输入的情况,一切要按照题目要求的字母序最小的情况进行,在不能比较的情况下给出字母序最小的答案也就是B,情况分类时主要是if语句比出最大值的使用,先随机挑选两个假设AB进行比较,胜出者不妨是A,则A与C比较,A>C则A最大(因为A既比B大也比C大),反之C>=A>B(因为A已经比B大了,要么C最大,要么A与C同为最大值),此时就要看如何处理AC了,如果仅仅找出最大值,不用分出来输出C一定最大,如果AC本质不同,那么需要细分一下A=C的情况进行处理。
实现代码
#include <iostream> #include <algorithm> using namespace std; int main(){ int count; cin >> count; char a; //甲的出拳 char b; //乙的出拳 int aWinCount = 0; //甲的胜场数 int bWinCount = 0;//乙的胜场数 int aEb = 0; //平场数 int aB = 0,aJ = 0,aC = 0; //甲用布、剪刀、石头的胜场 int bB = 0,bJ = 0,bC = 0;//乙用布、剪刀、石头的胜场 for(int i = 0; i < count; i++){ cin>>a>>b; switch(a){ case 'C': switch(b){ case 'C': aEb++; break; case 'B': bWinCount++; bB++; break; case 'J': aWinCount++; aC++; break; } break; case 'B': switch(b){ case 'C': aWinCount++; aB++; break; case 'B': aEb++; break; case 'J': bWinCount++; bJ++; break; } break; case 'J': switch(b){ case 'C': bWinCount++; bC++; break; case 'B': aWinCount++; aJ++; break; case 'J': aEb++; break; } break; } } cout<<aWinCount<<" "<<aEb<<" "<<count - aWinCount - aEb<<endl; cout<<bWinCount<<" "<<aEb<<" "<<count - bWinCount - aEb<<endl; if(aJ == 0 && aB == 0 && aC == 0){ //0输入的情况,特殊处理 cout<<'B'; }else{ //以下比较请在编程过程中细分 if(aJ > aB){ if(aJ > aC){ cout<<'J'; }else{ // J <= C cout<<'C'; } }else if(aJ == aB){ if(aJ >= aC){ cout<<'B'; }else{ cout<<'C'; } }else{//aB > aJ if(aB > aC){ //可以与下面的条件合成aB >= aC,下bB bC同 cout<<'B'; }else if(aB == aC){ cout<<'B'; }else{//aB < aC cout<<'C'; } } } cout<<" "; if(bJ == 0 && bC == 0 && bB == 0){ cout<<'B'; }else{ if(bJ > bB){ if(bJ > bC){ cout<<'J'; }else{//j<=c cout<<'C'; } }else if(bB == bJ){ if(bJ >= bC){ cout<<'B'; }else{ cout<<'C'; } }else{//bB > bJ if(bB > bC){ cout<<'B'; }else if(bB == bC){ cout<<'B'; }else{//b < c cout<<'C'; } } } return 0; }
结果
以上为笔者的暴力解决手段,下面来源于知乎-熊哥保佑你的解题思路,是巧用数组下标的思路,更简洁一些
他的思路排出了“分值”,本身就有优先级,那么就无需像上面那样考虑if-else罗列中考虑相等情况的特殊处理了,值得借鉴学习
#include<cstdio> int change(char c){ if(c=='B') return 0; if(c=='C') return 1; if(c=='J') return 2; } int main() { char mp[3]={'B','C','J'};//mp数组应该和change一样 int n; scanf("%d",&n); int times_A[3]={0},times_B[3]={0}; int hand_A[3]={0},hand_B[3]={0}; char c1,c2; int k1,k2; for(int i=0;i<n;i++){ getchar(); scanf("%c %c",&c1,&c2); k1=change(c1); k2=change(c2); if((k1+1)%3==k2){//可以把%3去掉来理解,看上面的change,前面的数可以赢后面的 times_A[0]++;//就是说如果前面的数加一等于后面的数,则前面赢后面 times_B[2]++;//tims_A[0]表示甲赢,times_A[1]表示平手,times_A[2]表甲输 hand_A[k1]++; }else if(k1==k2){ times_A[1]++; times_B[1]++; }else{ times_A[2]++; times_B[0]++; hand_B[k2]++; } } printf("%d %d %d\n",times_A[0],times_A[1],times_A[2]); printf("%d %d %d\n",times_B[0],times_B[1],times_B[2]); int id1=0,id2=0; for(int i=0;i<3;i++){//for循环,ifA[i]>A[max],max=i;这样求最大值 if(hand_A[i]>hand_A[id1]) id1=i; if(hand_B[i]>hand_B[id2]) id2=i; } printf("%c %c\n",mp[id1],mp[id2]); return 0; }