1 条题解

  • 2
    @ 2023-8-30 10:34:54

    模块化

    我以前其实并不是很注重模块化代码,因为觉得没必要,知道我遇见了这道题,我发现,我必须要模块化写代码,要不然实在过不了,

    • 就因为没有模块化,我都看不下去我写的代码,重构两次了。
    • 所以,我希望你也能认识到,这种大型模拟题代码必须模块化。

    思路

    总共分为五个模块。

    1. 输入数据,并保存在book数组中,一行一个book。
    2. 读取题目给出的时间复杂度。
    3. 判断给出代码是否符合格式。如果不符合,就输出ERR跳过后面循环。
    4. 计算时间复杂度。
    5. 判断时间复杂度是否与题目给出的相等。

    其中,1、2都是一些细节问题,不难,我们就先讲3模块。

    • 根据题意,有两种语法错误:
      1. F和E的数量不匹配。
      2. 定义的变量名有冲突。
    • 我们发现,其实这两个都不难,第一种于发错误,只要统计F、E的数量判断是否相等即可。
    • 而第二种错误,只要用数组记录变量名,每次开始循环判断变量名是否出现过,并且,每次循环结束删除变量名记录即可。
    • 这就是这种模拟题的特点,每个东西单说都不难,但要是混杂在一起,bug能让人头疼一整天,所以模块化就很重要。

    再看第四模块

    • 如果格式符合,那么我们就可以用一个变量ans记录实时时间复杂度,maxn记录最大时间复杂度。
    • 而后面又分三步
      1. 判断是否能进入循环。
      2. 判断这个循环是否处于第一步判断的不能进入的循环里面。
      3. 计算实时时间复杂度,并更新最大时间复杂度。
    • 而这三部单说也不难,但如果你搞混了,就有很多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

    [NOIP2017 提高组] 时间复杂度

    信息

    ID
    1386
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    36
    已通过
    18
    上传者