原题链接1018 锤子剪刀布
本题本来是一道简单题,但是我竟然提交了不下十次,就是有三个点是错误的,即测试点1、2、4。这也说明了思路是正确的。
其实问题出在了输出使得各自获胜次数最多的手势上面。
自定义测试样例
1
C C
按照题目意思,这种情况为进行了一次交锋,并且是平局,也就是说甲和乙都没有胜利,此时按照题意,在第三行应该输出的是B B,因为甲和乙都没有赢,即对于每个人来说,B、C、J三种手势,每个手势下赢的次数都是0,此时都应该输出B。
原代码为
#include <iostream>
#include <map>
using namespace std;
int jw = 0,yw = 0,tiecnt = 0;
map<char,int> mp,cntj,cnty;
char getans(map<char,int>& cnt){
//找出使得当前人获胜次数最多的手势
char ans;
for(auto it=cnt.begin();it!=cnt.end();it++){
if(it == cnt.begin()) ans = it->first;
else if(it->second > cnt[ans]) ans = it->first;
}
return ans;
}
int main()
{
mp['B']=0,mp['C']=1,mp['J']=2;
int n;
scanf("%d",&n);
for(int i=0;i<n;i++){
char j,y;
scanf(" %c %c",&j,&y);
if(j == y) tiecnt++;
else if((mp[j]+1)%3==mp[y]){
jw++;
cntj[j]++;
}
else {
yw++;
cnty[y]++;
}
}
printf("%d %d %d\n",jw,tiecnt,yw);
printf("%d %d %d\n",yw,tiecnt,jw);
printf("%c %c\n",getans(cntj),getans(cnty));
return 0;
}
单独来看里面获得使得当前人获胜次数最多的手势的代码
char getans(map<char,int>& cnt){
//找出使得当前人获胜次数最多的手势
char ans;
for(auto it=cnt.begin();it!=cnt.end();it++){
if(it == cnt.begin()) ans = it->first;
else if(it->second > cnt[ans]) ans = it->first;
}
return ans;
}
问题就出在这里面,这是因为,map<char,int> cnt,并不一定含有全部的B、C、J映射。
比如当数据为上述自定义的数据时,在整个main的for循环中,仅仅是走了平局的分支,其余两个分支都没有走,也就是说,此时cntj和cnty均是空的,此时再去查询,并不是想象中的依次遍历B、C、J映射。
可以在getans函数中将ans赋初值为‘B’,即
char getans(map<char,int>& cnt){
char ans='B';//赋初值为‘B’
for(auto it=cnt.begin();it!=cnt.end();it++){
if(it == cnt.begin()) ans = it->first;
else if(it->second > cnt[ans]) ans = it->first;
}
return ans;
}
或者是
char getans(map<char,int>& cnt){
char ans='B';
char ch[] = "BCJ";
for(int i=0;i<3;i++){
if(cnt[ch[i]]>cnt[ans]) ans=ch[i];
}
return ans;
}
总之
map与unordered_map是随着数据插入而逐渐插入映射的。并不是想象中的数据。