【NOIP2017】时间复杂度

题面

小明正在学习一种新的编程语言 A++,刚学会循环语句的他激动地写了好多程序并给出了他自己算出的时间复杂度,可他的编程老师实在不想一个一个检查小明的程序,于是你的机会来啦!下面请你编写程序来判断小明对他的每个程序给出的时间复杂度是否正确。

A++语言的循环结构如下:

F i x y
    循环体
E

其中“F i x y”表示新建变量 i(变量 i 不可与未被销毁的变量重名)并初始化为x,然后判断 i 和 y 的大小关系,若 i 小于等于 y 则进入循环,否则不进入。每次循环结束后 i 都会被修改成 i+1,一旦 i 大于 y 终止循环。

x 和 y 可以是正整数(x和y的大小关系不定)或变量 n 。n 是一个表示数据规模的变量,在时间复杂度计算中需保留该变量而不能将其视为常数,该数远大于 100 。

“E”表示循环体结束。循环体结束时,这个循环体新建的变量也被销毁。

注:本题中为了书写方便,在描述复杂度时,使用大写英文字母“O”表示通常意义下“Θ”的概念。

输入格式:

输入文件第一行一个正整数 t ,表示有 t(t ≤10)个程序需要计算时间复杂度。每个程序我们只需抽取其中“F i x y”和“E”即可计算时间复杂度。注意:循环结构允许嵌套。

接下来每个程序的第一行包含一个正整数 L 和一个字符串,L 代表程序行数,字符串表示这个程序的复杂度,“O(1)”表示常数复杂度,“O(n^w)”表示复杂度为 n^w,其中 w 是一个小于 100 的正整数(输入中不包含引号),输入保证复杂度只有 O(1) 和 O(n^w) 两种类型。

接下来 L 行代表程序中循环结构中的“F i x y”或者“E”。

程序行若以“F”开头,表示进入一个循环,之后有空格分离的三个字符(串) i x y,其中 i 是一个小写字母(保证不为“n”),表示新建的变量名,x 和 y 可能是正整数或 n,已知若为正整数则一定小于 100。

程序行若以“E”开头,则表示循环体结束。

输出格式:

输出文件共 t 行,对应输入的 t 个程序,每行输出“Yes”或“No”或者“ERR”(输出中不包含引号),若程序实际复杂度与输入给出的复杂度一致则输出“Yes”,不一致则输出“No”,若程序有语法错误(其中语法错误只有:①F和E不匹配;②新建的变量与已经存在但未被销毁的变量重复两种情况),则输出“ERR”。

注意:即使在程序不会执行的循环体中出现了语法错误也会编译错误,要输出“ERR”。

分析

去年,我只会做10分的。真的是细节很坑吧,我发现模拟题不能照着样例来模拟,先别看样例,自己想清楚所有情况,列在草稿纸上画着。

我就漏了循环不是严格嵌套的,以及x和y都是常数,但是x比y大这种。用栈维护一下顺序,就没啥说的了。

代码

  1. #include<bits/stdc++.h>  
  2. using namespace std;  
  3. #define N 110  
  4. int t,n,ok,x,y,ans,is1,tmp,fzd,upd,top,xisn,yisn,lenx,leny,flag;  
  5. int zm[40],sta[N];  
  6. char s[N],F[N],I[N],X[N],Y[N];  
  7. inline void init()  
  8. {  
  9.     ok=1;top=tmp=ans=is1=upd=flag=0;  
  10.     memset(zm,0,sizeof(zm));  
  11.     memset(sta,0,sizeof(sta));  
  12. }  
  13. int main()  
  14. {  
  15.     scanf("%d",&t);  
  16.     while(t--)  
  17.     {  
  18.         init();  
  19.         scanf("%d%s",&n,s);  
  20.         if(n&1)ok=0;  
  21.         if(s[2]=='1')is1=1;  
  22.         else   
  23.         {  
  24.             fzd=s[4]-'0';      
  25.             if(s[5]>='0'&&s[5]<='9')  
  26.                 fzd=fzd*10+s[5]-'0';  
  27.         }  
  28.         for(int i=1;i<=n;i++)  
  29.         {  
  30.             scanf("%s",F);  
  31.             if(F[0]=='F')  
  32.             {  
  33.                 xisn=0,yisn=0;x=0;y=0;  
  34.                 scanf("%s%s%s",I,X,Y);  
  35.                 if(zm[I[0]-'a'])ok=0;  
  36.                 zm[I[0]-'a']=1;sta[++top]=I[0]-'a';  
  37.                 lenx=strlen(X),leny=strlen(Y);  
  38.                 if(lenx==1)  
  39.                     if(X[0]=='n') xisn=1;  
  40.                     else x=X[0]-'0';  
  41.                 else  
  42.                     x=X[0]-'0',x=x*10+X[1]-'0';      
  43.                 if(leny==1)  
  44.                     if(Y[0]=='n') yisn=1;  
  45.                     else y=Y[0]-'0';  
  46.                 else  
  47.                     y=Y[0]-'0',y=y*10+Y[1]-'0';  
  48.                 if(upd)continue;      
  49.                 if(!xisn&&yisn)tmp++;  
  50.                 if((xisn&&!yisn)||(x&&y&&(x>y)))flag=ans,upd=top;  
  51.             }  
  52.             else  
  53.             {    if(upd)upd--;  
  54.                 zm[sta[top]]=0;top--;  
  55.                 ans=max(ans,tmp),tmp--;  
  56.                 if(top<0)ok=0;  
  57.                 if(top==0)  
  58.                 {  
  59.                     ans=max(ans,tmp),tmp=0;  
  60.                     if(upd)  
  61.                     {  
  62.                         ans=max(ans,flag);  
  63.                         flag=0,upd=0;  
  64.                     }  
  65.                 }  
  66.             }   
  67.         }  
  68.         if(top)ok=0;  
  69.         if(!ok){printf("ERR ");continue;}  
  70.         if(is1)  
  71.         {  
  72.   
  73.             if(!ans)printf("Yes ");  
  74.             else printf("No ");  
  75.            
  76.         }      
  77.         else  
  78.         {  
  79.             if(ans==fzd)printf("Yes ");  
  80.             else printf("No ");  
  81.   
  82.         }  
  83.     }   
  84.     return 0;  
  85. }  
原文地址:https://www.cnblogs.com/NSD-email0820/p/9826260.html