洛谷P3952 时间复杂度
题目描述
小明正在学习一种新的编程语言 A++,刚学会循环语句的他激动地写了好多程序并 给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序, 于是你的机会来啦!下面请你编写程序来判断小明对他的每个程序给出的时间复杂度是否正确。
A++语言的循环结构如下:
F i x y
循环体
E
其中F i x y表示新建变量 ii(变量 ii 不可与未被销毁的变量重名)并初始化为 xx, 然后判断 ii 和 yy 的大小关系,若 ii 小于等于 yy 则进入循环,否则不进入。每次循环结束后 ii 都会被修改成 i +1i+1,一旦 ii 大于 yy终止循环。
xx 和 yy 可以是正整数(xx 和 yy 的大小关系不定)或变量 nn。nn 是一个表示数据规模的变量,在时间复杂度计算中需保留该变量而不能将其视为常数,该数远大于 100100。
“E”表示循环体结束。循环体结束时,这个循环体新建的变量也被销毁。
注:本题中为了书写方便,在描述复杂度时,使用大写英文字母“O”表示通常意义下“Θ”的概念。
输入格式
输入文件第一行一个正整数 tt,表示有 tt(t \le 10t≤10)个程序需要计算时间复杂度。 每个程序我们只需抽取其中 F i x y和E即可计算时间复杂度。注意:循环结构 允许嵌套。
接下来每个程序的第一行包含一个正整数 LL 和一个字符串,LL 代表程序行数,字符 串表示这个程序的复杂度,O(1)表示常数复杂度,O(n^w)表示复杂度为n^wnw,其 中w是一个小于100的正整数(输入中不包含引号),输入保证复杂度只有O(1)和O(n^w) 两种类型。
接下来 LL 行代表程序中循环结构中的F i x y或者 E。 程序行若以F开头,表示进入一个循环,之后有空格分离的三个字符(串)i x y, 其中 ii 是一个小写字母(保证不为nn),表示新建的变量名,xx 和 yy 可能是正整数或 nn ,已知若为正整数则一定小于 100。
程序行若以E开头,则表示循环体结束。
输出格式
输出文件共 tt 行,对应输入的 tt 个程序,每行输出Yes或No或者ERR(输出中不包含引号),若程序实际复杂度与输入给出的复杂度一致则输出Yes,不一致则输出No,若程序有语法错误(其中语法错误只有: ① F 和 E 不匹配 ②新建的变量与已经存在但未被销毁的变量重复两种情况),则输出ERR 。
注意:即使在程序不会执行的循环体中出现了语法错误也会编译错误,要输出 ERR。
//将数字记为k
输入的格式有三种:
k O(n^k)
F i x y
E
第二种由于不会出现以变量作为x,y的值,如:
F i 1 n
F j i+1 n
则没有必要保存各个变量的值,只关心代码是否合法和时间复杂度就行了。
对于时间复杂度:
F i k k = F i n k = O(1)
只有 F i k n = O(n)
则也没有必要保存k的值,只须关注x,y是否等于n和循环成立即可。
剩下的就是模拟。
代码:
#include<iostream> #include<stack> #include<cstring> using namespace std; stack<bool> q; char st[105]; bool fnd(char a); void mfnd(); int main() { string inERR,ai,aj; int ans,t,i,j,k,kline,now,nans,fans,zERR,reERR; char a; bool ERR; cin>>t; for(int o=1;o<=t;o++) { memset(st,0,sizeof(st)); ERR=0; now=0; nans=0; fans=0; zERR=0; reERR=0; cin>>kline>>a>>a>>a; if(a=='1')//ans=0 O(1) ans=k O(n^k) { ans=0; cin>>a; } else cin>>a>>ans>>a; for(int u=1;u<=kline;u++) { cin>>a; if(ERR==1&&a=='F') cin>>inERR>>inERR>>inERR; else if(ERR==1) continue; else { if(a=='F') { cin>>a; if(fnd(a)) { ERR=1; reERR=1; cin>>inERR>>inERR; continue; } cin>>ai>>aj; now++; if(aj=="n"&&ai!="n") { q.push(1); nans++; } else q.push(0); if((ai>aj&&ai.size()>=aj.size())||(ai=="n"&&aj!="n"))//判断循环是否能执行 zERR++; if((nans>fans)&&(zERR==0)) fans=nans; } else if(a=='E') { mfnd(); if(zERR!=0) zERR--; now--; if(now<0) { ERR=1; cout<<"ERR"<<endl; continue; } if(q.top()==1) nans--; q.pop(); if(now==0) { memset(st,0,sizeof(st)); zERR=0; } } } } if(reERR) cout<<"ERR"<<endl; else if(now!=0&&ERR!=1) cout<<"ERR"<<endl; else if(fans==ans&&ERR!=1) cout<<"Yes"<<endl; else if(fans!=ans&&ERR!=1) cout<<"No"<<endl; } system("pause"); return 0; } bool fnd(char a) { int i; i=0; while(st[i]!=0) { if(st[i]==a) return 1; i++; } i=0; while(st[i]!=0) i++; st[i]=a; return 0; } void mfnd() { int i; i=0; while(st[i]!=0) i++; if(i==0) return ; st[i-1]=0; return ; }
其实洛谷的数据还挺水的,没有出现在循环中弹出的操作,都是所有循环结束后一次性弹出。

浙公网安备 33010602011771号