[题解] [NOIP2017] 时间复杂度
[题解] NOIP2017 时间复杂度
题目描述#
小明正在学习一种新的编程语言 A++,刚学会循环语句的他激动地写了好多程序并 给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序, 于是你的机会来啦!下面请你编写程序来判断小明对他的每个程序给出的时间复杂度是否正确。
A++语言的循环结构如下:
F i x y
循环体
E
其中F
E 表示循环体结束。循环体结束时,这个循环体新建的变量也被销毁。
注:本题中为了书写方便,在描述复杂度时,使用大写英文字母
输入格式#
输入文件第一行一个正整数
接下来每个程序的第一行包含一个正整数
接下来
程序行若以F开头,表示进入一个循环,之后有空格分离的三个字符(串)
程序行若以E开头,则表示循环体结束。
输出格式#
输出文件共
注意:即使在程序不会执行的循环体中出现了语法错误也会编译错误,要输出 ERR。
题解#
实际上一个A++程序的时间复杂度就是最高的带n循环嵌套层数。故在使用栈匹配循环头和循环结束语句的过程中模拟统计带n循环层数即可。
统计时需要注意两点,一是循环无法进入的情况,包括:
二是语法错误。语法错误一共有三种情况,包括:
- 出现了还未被释放的变量(使用vis数组记录)
- 在任意时刻E多过了F(判断栈空)
- 在最后时刻F多过了E(判断栈非空)
统计结束后,对比统计结果与题目给出的答案即可。
调试过程#
对比初版代码,共发现以下错误:
- 没有考虑变量被回收的情况,没有重置vis标记
时可以进入循环但被我卡掉了,多加了不必要的判断- 在还原tmp标记时没有考虑tmp修改时的条件(只有
的时候才修改,所以只有able为0时才需要还原标记)
AC代码#
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <string>
#include <stack>
#include <queue>
#define int long long
using namespace std;
bool vis[30]; // 用于标识字母是否出现过
struct LoopNode {
char id;
int x = 0, y = 0;
};
stack <LoopNode> st;
LoopNode readNode() {
LoopNode loopNode;
char ch = getchar();
while (ch == ' ') ch = getchar();
if (ch != 'n') {
while (isdigit(ch)) {
loopNode.x = (loopNode.x * 10) + ch - '0';
ch = getchar();
}
} else {
ch = getchar();
}
while (ch == ' ') ch = getchar();
if (ch != 'n') {
while (isdigit(ch)) {
loopNode.y = (loopNode.y * 10) + ch - '0';
ch = getchar();
}
} else {
ch = getchar();
}
return loopNode;
}
int readTar() {
int x = 0;
char ch = getchar();
while (ch != '(') ch = getchar();
ch = getchar();
if (ch == '1') {
while (ch != ')') ch = getchar();
return 0;
}
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) {
x = x * 10 + ch - '0';
ch = getchar();
}
while (ch != ')') ch = getchar();
return x;
}
signed main() {
// freopen("test.in", "r", stdin);
int t;
cin >> t;
while (t--) {
memset(vis, 0, sizeof vis);
int n;
cin >> n;
int tar = readTar();
bool ok = true;
int able = 0; //记录当前有无不可进入的循环
int tmp = 0; //记录当前栈中的有效循环数
int ans = 0;
for (int i = 1; i <= n; i++) {
char op;
cin >> op;
if (op == 'F') {
char ch;
cin >> ch;
if (vis[ch - 'a']) ok = false;
else vis[ch - 'a'] = true;
LoopNode loopNode = readNode();
loopNode.id = ch;
st.push(loopNode);
if ((!loopNode.x && loopNode.y) || (loopNode.x && loopNode.y && loopNode.x > loopNode.y)) //无法进入:n,1 2,1
able++;
if (able) continue;
if (loopNode.x && !loopNode.y) tmp++;
} else if (op == 'E') {
if (st.empty()) {
ok = false;
} else {
ans = max(ans, tmp);
LoopNode loopNode = st.top();
if ((!loopNode.x && loopNode.y) || (loopNode.x && loopNode.y && loopNode.x > loopNode.y)) //无法进入:n,1 2,1
able--;
if (loopNode.x && !loopNode.y && able == 0) tmp--;
vis[loopNode.id - 'a'] = false;
st.pop();
}
}
}
if (!st.empty()) {
ok = false;
while (!st.empty()) st.pop();
}
if (ok) {
if (ans == tar) cout << "Yes\n";
else cout << "No\n";
} else {
cout << "ERR\n";
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】