题目:1044 火星数字 (20 分)
火星人是以 13 进制计数的:
- 地球人的 0 被火星人称为 tret。
- 地球人数字 1 到 12 的火星文分别为:jan, feb, mar, apr, may, jun, jly, aug, sep, oct, nov, dec。
- 火星人将进位以后的 12 个高位数字分别称为:tam, hel, maa, huh, tou, kes, hei, elo, syy, lok, mer, jou。
例如地球人的数字
29
翻译成火星文就是hel mar
;而火星文elo nov
对应地球数字115
。为了方便交流,请你编写程序实现地球和火星数字之间的互译。输入格式:
输入第一行给出一个正整数 N(<),随后 N 行,每行给出一个 [0, 169) 区间内的数字 —— 或者是地球文,或者是火星文。
输出格式:
对应输入的每一行,在一行中输出翻译后的另一种语言的数字。
输入样例:
4 29 5 elo nov tam
输出样例:
hel mar may 115 13
思路:
- 地球数字对应的火星文开数组对应下标进行利用
- 判断是地球文还是火星文。可以根据第一位字符判断,如果是数字字符那就是数字字符串的地球文,否则就是火星文。或者用C++函数库中cctype头文件中包含的isdigit()函数判断是不是十进制的字符。
- 若是地球文则要将字符类型转换为整型int,可以用stoi()函数,也可以用stringstream类型,但据说stoi不是一个函数库,最好少用。
注意:如果是0, 输出tret好像会自动换行,不知道为什么,应该是我的代码的问题,看别人的好像都不会。这个点是在测试点1,我格式错误了,所以就直接特判了。
注意13开始就是高位数了! - 若是火星文,凭借有无空格区分两个火星数字,然后将得到的数字进行进制转换。
代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <cctype> //isdigit() 4 #include <iostream> 5 #include <sstream> //包含stringstream 6 #include <cmath> 7 #include <algorithm> 8 #include <string> //stoi() 9 #include <stack> 10 #include <queue> 11 #include <vector> 12 #include <map> 13 using namespace std; 14 15 int main() 16 { 17 int n; 18 char low[13][5]={"tret","jan","feb","mar","apr","may","jun","jly","aug","sep","oct","nov","dec"}; 19 char high[13][5]={"","tam","hel","maa","huh","tou","kes","hei","elo","syy","lok","mer","jou"}; 20 scanf("%d", &n); 21 string s; 22 getchar(); //后面使用getline()需要在这里接收输入的回车, 否则会出错 23 for(int i = 0; i < n; i++) 24 { 25 getline(cin, s); 26 if(s[0] >= '0' && s[0] <= '9') //地球文-->火星文 27 { 28 int num; 29 stringstream ss; 30 ss << s; 31 ss >> num; //将num转为int类型 32 int flag = 0; 33 if(num == 0) 34 printf("tret"); 35 if(num < 13 && num > 0) 36 printf("%s\n", low[num]); 37 if(num >= 13) //如果数字大于等于13就需要输出高位 38 { 39 printf("%s", high[num/13]); 40 flag = 1; 41 } 42 if(num%13 == 0) //我不加这个if语句进行处理且num会被13整除的话,在输出高位后,后面又会多出个其他字符,导致答案错误,测试点在2、4 43 { 44 printf("\n"); 45 continue; 46 } 47 if(flag && num%13 != 0) 48 { 49 printf(" %s\n", low[num%13]); //在有高位的情况下,低位为零不输出 50 } 51 } 52 else //火星文-->地球文 53 { 54 string s1 = "", s2 = ""; 55 int m = 0, k = 0; 56 for(int i = 0; i < s.length(); i++) 57 { 58 if(s[i] != ' ') //以空格为分界线区分两个字符串 59 s1 += s[i]; 60 else 61 { 62 s2 = s1; //s2是高位 63 s1 = ""; 64 } 65 } 66 for(int i = 0; i < 13; i++) //因为可能没有空格,所以s1可能为高位也可能为低位 67 { 68 if(s1 == low[i]) 69 m = i; 70 if(s1 == high[i]) 71 k = i; 72 if(s2 == high[i]) 73 k=i; 74 } 75 printf("%d\n", k*13+m); 76 } 77 } 78 return 0; 79 }
总结:
oj过题两种方式:一、知道测试点数据利用特判过;二、完美的AC代码,靠硬实力敲。前面那种方式类似投机取巧。
最初不是用空格区分两个火星数字,代码就搞不好,在带有空格的字符串中可以利用空格来判断是否开始新的单词。学C的时候课本上有过这样的例子,只能怪自己大一上不好好敲代码以及不做任何总结。
有时虽然有思路,但是代码却不能很好实现,或者比较冗长,就是代码敲的少的问题,功底薄弱。利用STL容器和各函数库可以使代码简便很多,所以总结除了题解,还应该总结下学到的STL容器和函数库的应用。