PAT 乙级 1037
题目
题目地址:PAT 乙级 1037
题解
本题有两个版本的代码,初版因为种种问题写得比较繁琐,具体的分析见后文,更新的之后的版本相对来说要好很多,代码也比较清晰简洁。
初版的代码主要有如下几方面的问题:
1. 代码繁琐,把简单的问题复杂化。
2. 刷题一直在用C++,虽说C和C++相似,但是思路一直在框定在C++的范围内,不够灵活。
下面就具体代码进行分析:
代码
1 #include <iostream> 2 #include <string> 3 #include <cmath> 4 using namespace std; 5 6 struct Data { 7 string str; 8 int g; 9 int s; 10 int k; 11 int Q; 12 }; 13 14 int str2int(string s) { 15 int num = 0; 16 int cnt = 0; 17 for (int i = s.size() - 1; i >= 0; i--) { 18 num += (int(s[i]) - 48) * pow(10, cnt); 19 cnt++; 20 } 21 return num; 22 } 23 24 void str2num(Data &s) { 25 int cnt = 0, loc = 0; 26 for (int i = 0; i < s.str.size(); i++) { 27 string tmp; 28 if (s.str[i] == '.' && cnt == 0) { 29 tmp = s.str.substr(0, i); 30 s.g = str2int(tmp); 31 loc = i; 32 cnt++; 33 } 34 else if (s.str[i] == '.' && cnt == 1) { 35 tmp = s.str.substr(loc + 1, i - loc - 1); 36 s.s = str2int(tmp); 37 loc = i; 38 cnt++; 39 } 40 else if (i == s.str.size() - 1) { 41 tmp = s.str.substr(loc + 1, i - loc); 42 s.k = str2int(tmp); 43 loc = i; 44 } 45 } 46 } 47 48 void compare(Data &a, Data &b) { 49 a.Q = 0; 50 b.Q = 0; 51 if (a.g > b.g) 52 a.Q += 5; 53 else if (a.g < b.g) 54 b.Q += 5; 55 if (a.s > b.s) 56 a.Q += 3; 57 else if (a.s < b.s) 58 b.Q += 3; 59 if (a.k > b.k) 60 a.Q++; 61 else if (a.k < b.k) 62 b.Q++; 63 } 64 65 int main() { 66 Data P, A; 67 cin >> P.str >> A.str; 68 str2num(P); 69 str2num(A); 70 compare(P, A); 71 int g = 0, s = 0, k = 0; 72 if (P.Q < A.Q) { 73 if (A.k >= P.k) 74 k = A.k - P.k; 75 else { 76 A.s--; 77 A.k += 29; 78 k = A.k - P.k; 79 } 80 if (A.s >= P.s) 81 s = A.s - P.s; 82 else { 83 A.g--; 84 A.s += 17; 85 s = A.s - P.s; 86 } 87 g = A.g - P.g; 88 } 89 else { 90 if (P.k >= A.k) 91 k = P.k - A.k; 92 else { 93 P.s--; 94 P.k += 29; 95 k = P.k - A.k; 96 } 97 if (P.s >= A.s) 98 s = P.s - A.s; 99 else { 100 P.g--; 101 P.s += 17; 102 s = P.s - A.s; 103 } 104 g = -(P.g - A.g); 105 } 106 cout << g << "." << s << "." << k << endl; 107 108 return 0; 109 }
1. 在接收输入数据时,使用string接收数据,之后再进行一系列转化,最后才能得到int类型的数据,这个过程就很“笨拙”;因为输入的格式固定,所以如果使用C语言的scanf的格式控制符,就可以极大地简化数据接收部分的代码;
2. 同时在写代码过程中,帮助我理清了一个问题,也是我一直忽视的一个点:结构体在函数内部对数据的操作不能赋给主函数中的实参,现在想来也是很简单的一个问题,函数内部的变量只是局部变量,这句话在学C的时候看到过很多次,当时还不能很清楚地理解;形参传入后仍然只是一个局部变量,函数内开的一切变量作用范围都只在函数中,一旦函数调用结束,当前存在函数变量中的数据都随函数的调用结束一并被清除;
解决方式有几种,一是调用结束后将数据返回,二是采用全局变量,三是以引用的方式传参,这里选择第三种方式有效地解决了这一问题。
更新之后的代码相对而言简洁得多,思路是把所有输入数据全部转化为最小进制的单位,相减之后再化回不同的单位。
代码
1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 5 int main() { 6 int g1 = 0, s1 = 0, k1 = 0; 7 int g2 = 0, s2 = 0, k2 = 0; 8 scanf("%d.%d.%d %d.%d.%d", &g1, &s1, &k1, &g2, &s2, &k2); 9 long cnt1 = 0, cnt2 = 0; 10 cnt1 = (g1 * 17 + s1) * 29 + k1; 11 cnt2 = (g2 * 17 + s2) * 29 + k2; 12 long tmp = cnt2 - cnt1; 13 if (tmp < 0) { 14 printf("-"); 15 tmp = -tmp; 16 } 17 int g = 0, s = 0, k = 0; 18 g = tmp / 17 / 29; 19 s = (tmp - g * 17 * 29) / 29; 20 k = tmp - g * 17 * 29 - s * 29; 21 printf("%d.%d.%d\n", g, s, k); 22 23 return 0; 24 }