1 条题解
-
2
模块化
我以前其实并不是很注重模块化代码,因为觉得没必要,知道我遇见了这道题,我发现,我必须要模块化写代码,要不然实在过不了,
- 就因为没有模块化,我都看不下去我写的代码,重构两次了。
- 所以,我希望你也能认识到,这种大型模拟题代码必须模块化。
思路
总共分为五个模块。
- 输入数据,并保存在book数组中,一行一个book。
- 读取题目给出的时间复杂度。
- 判断给出代码是否符合格式。如果不符合,就输出ERR跳过后面循环。
- 计算时间复杂度。
- 判断时间复杂度是否与题目给出的相等。
其中,1、2都是一些细节问题,不难,我们就先讲3模块。
- 根据题意,有两种语法错误:
- F和E的数量不匹配。
- 定义的变量名有冲突。
- 我们发现,其实这两个都不难,第一种于发错误,只要统计F、E的数量判断是否相等即可。
- 而第二种错误,只要用数组记录变量名,每次开始循环判断变量名是否出现过,并且,每次循环结束删除变量名记录即可。
- 这就是这种模拟题的特点,每个东西单说都不难,但要是混杂在一起,bug能让人头疼一整天,所以模块化就很重要。
再看第四模块
- 如果格式符合,那么我们就可以用一个变量ans记录实时时间复杂度,maxn记录最大时间复杂度。
- 而后面又分三步
- 判断是否能进入循环。
- 判断这个循环是否处于第一步判断的不能进入的循环里面。
- 计算实时时间复杂度,并更新最大时间复杂度。
- 而这三部单说也不难,但如果你搞混了,就有很多bug。
AC代码
看完了思路,想必你已经有了思路,下面,就让我们看看代码吧:
#include<bits/stdc++.h> using namespace std; //全局变量。 int t, rtf, jtf; //输入保存。 string book[105]; //统计f、e数量。 int fl, el; //模块一对应变量。 string yi; int n; void Read() {//模块一,读入数据。 cin >> n; getline(cin, yi); //去掉空格。 yi = yi.substr(1); for (int i = 1; i <= n; i++) getline(cin, book[i]); return; } int Cut(int w, string s) {//切割函数。 //用于获得字符串从w号字符后面的数字。 int i = w, res = 0, len = s.length(); while (s[i] >= '0' && s[i] <= '9' && i < len) { res = res * 10 + (s[i] - '0'); i++; } return res; } bool check(string s, int ji) {//检查是否能进入循环。 //a是变量初始化的数,b是终止循环条件的数。 if (ji != 0 || s[0] == 'E') return false; int a = Cut(4, s); int i = 4; while (s[i] >= '0' && s[i] <= '9') i++; int b = Cut(i + 1, s); //如果a>b或者a=n,b!=n就不能进入循环。 return ((a > b && s[s.length() - 1] != 'n') || (s[4] == 'n' && s[s.length() - 1] != 'n')); } int Tcm() {//模块二:读取时间复杂度。 if (yi[2] != 'n') return 0; else { return Cut(4, yi); } } bool Pange() {//模块三:判断是否符合各式。 fl = el = 0; //第一步,判断F、E的数量是否一致 for (int i = 1; i <= n; i++) { //el、fl分别统计e、f的数量。 if (book[i][0] == 'E') el++; else if (book[i][0] == 'F') fl++; } //如果不相等,那格式错误。 if (el != fl) return true; //第二步,判断变量名是否冲突 //用于记录变量名。 char vbl[105] = { ' ' }; int k = 1; for (int i = 1; i <= n; i++) { if (book[i][0] == 'F') { //判断这个变量名是否与前面已有的变量名冲突。 for (int j = 1; j < k; j++) { if (vbl[j] == book[i][2]) return true; } //如果不冲突,那就加入。 vbl[k++] = book[i][2]; } else if (book[i][0] == 'E') { //变量名记录后退。 k--; } } //如果前面都通过了,那他就符合各式。 return false; } int CountTf() {//模块四:计算时间复杂度。 int ans = 0, maxn = 0; int ji = 0, lin; for (int i = 1; i <= n; i++) { //步骤一,检查是否能进入循环。 if (check(book[i], ji)) { ji = i; lin = i; continue; } //步骤二,检查ji是否不为0,如果不为0,那说明这个循环无法进入。 if (ji != 0) { if (book[i][0] == 'F') { lin++; } else if (book[i][0] == 'E') { lin--; } //如果lin小于等于ji,说明不能进入的循环已经结束。 if (lin <= ji) { ji = 0; } continue; } //步骤三,判断时间复杂度是否增加。 if (book[i][book[i].length() - 1] == 'n' && book[i][4] != 'n') { ans++; maxn = max(ans, maxn); } //减少。 else if (book[i][0] == 'E') { if (ans > 0) ans--; } } //返回最大时间复杂度。 return maxn; } void Opa(int a, int b) {//模块五:输出答案。 if (a == b) { cout << "Yes\n"; } else { cout << "No\n"; } return; } int main() { cin >> t; while (t--) { //模块一:读入数据,储存在book数组中(OK)。 Read(); //模块二:读取时间复杂度(OK)。 rtf = Tcm(); //模块三:判断是否符合格式。 if (Pange()) { cout << "ERR\n"; continue; } //模块四:计算时间复杂度。 jtf = CountTf(); //模块五:判断输出答案。 Opa(rtf, jtf); } return 0; }
看完代码是不是觉得有点长,其实你看着长,写起来也挺快,毕竟每部分都不难,一点一点写、测试一个半小时就能搞定,而且基本不用修bug,有bug也修的很快。
- 1
信息
- ID
- 1386
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 4
- 标签
- 递交数
- 36
- 已通过
- 18
- 上传者