[NOIP2017]时间复杂度

题目描述

小明正在学习一种新的编程语言 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 10t10)个程序需要计算时间复杂度。 每个程序我们只需抽取其中F i x yE即可计算时间复杂度。注意:循环结构 允许嵌套。

接下来每个程序的第一行包含一个正整数 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 个程序,每行输出YesNo或者ERR(输出中不包含引号),若程序实际复杂度与输入给出的复杂度一致则输出Yes,不一致则输出No,若程序有语法错误(其中语法错误只有: ① F 和 E 不匹配 ②新建的变量与已经存在但未被销毁的变量重复两种情况),则输出ERR 。

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

 

输入输出样例

输入样例#1:  复制
8
2 O(1)
F i 1 1
E
2 O(n^1)
F x 1 n
E
1 O(1)
F x 1 n
4 O(n^2)
F x 5 n
F y 10 n
E
E
4 O(n^2)
F x 9 n
E
F y 2 n
E
4 O(n^1)
F x 9 n
F y n 4
E
E
4 O(1)
F y n 4
F x 9 n
E
E
4 O(n^2)
F x 1 n
F x 1 10
E
E
输出样例#1:  复制
Yes
Yes
ERR
Yes
No
Yes
Yes
ERR

说明

【输入输出样例解释1】

第一个程序 ii 从 1 到 1 是常数复杂度。

第二个程序 xx 从 1 到 nn 是 nn 的一次方的复杂度。

第三个程序有一个 F 开启循环却没有 E 结束,语法错误。

第四个程序二重循环,nn 的平方的复杂度。

第五个程序两个一重循环,nn 的一次方的复杂度。

第六个程序第一重循环正常,但第二重循环开始即终止(因为nn远大于100,100大于4)。

第七个程序第一重循环无法进入,故为常数复杂度。

第八个程序第二重循环中的变量 xx 与第一重循环中的变量重复,出现语法错误②,输出 ERR

【数据规模与约定】

对于 30\%30%的数据:不存在语法错误,数据保证小明给出的每个程序的前 L/2L/2 行一定为以 F 开头的语句,第 L/2+1L/2+1 行至第 LL 行一定为以 EE 开头的语句,L \le 10L10,若 xx、yy 均 为整数,xx 一定小于 yy,且只有 yy 有可能为 nn。

对于 50\%50%的数据:不存在语法错误,L \le 100L100,且若 xx、yy 均为整数,xx 一定小于 yy, 且只有 yy 有可能为 nn。

对于 70\%70%的数据:不存在语法错误,L \le 100L100。

对于 100\%100%的数据:L \le 100L100。

 

终于把这道题写出来了QAQ,写+调一共一个半小时

以前看到这种题还是很害怕的。现在发现在做题前要先理清思路,把细节在脑子里想好,最好写到纸上来,然后做的时候给每个变量都打上注释

这种题最怕做着做着脑子乱掉了,那就凉了,一定要趁头脑清醒的时候一鼓作气敲完它

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 using namespace std;
  5 int T;//数据组数 
  6 int len;//指令条数
  7 int fzd;//题目给出时间复杂度
  8 int maxn;//执行程序时得到最大的时间复杂度
  9 struct order
 10 {
 11     int opt;//类型:1->循环 2->结束
 12     int ch;//变量名
 13     int x,y;// 10000表示为n 
 14 }q[101];
 15 int top;
 16 int st[101]; 
 17 bool vis[101];//是否存在该变量 
 18 bool flag[101];//这个位置是否算入时间复杂度了
 19 int read()
 20 {
 21     char ch=getchar(); int x=0;
 22     while((ch>'9'||ch<'0')&&ch!='n') ch=getchar();
 23     if(ch=='n') {getchar();return 10000;}    
 24     while(ch<='9'&&ch>='0') x=x*10+ch-'0',ch=getchar();
 25     return x;
 26 }
 27 void clear()
 28 {
 29     len=fzd=maxn=top=0;
 30     memset(st,0,sizeof(st));
 31     memset(vis,0,sizeof(vis));
 32     memset(flag,0,sizeof(flag));
 33     memset(q,0,sizeof(q));
 34 }
 35 int getfzd()
 36 {
 37     char c=getchar();int x=0;
 38     while(c!='(') c=getchar();
 39     c=getchar();
 40     if(c=='1')  {c=getchar();return 0;}
 41     while(c>'9'||c<'0') c=getchar();
 42     while(c<='9'&&c>='0') x=x*10+c-'0',c=getchar();
 43     c=getchar(); return x;
 44 }
 45 bool judge()
 46 {
 47     int top=0;
 48     for(int i=1;i<=len;i++)
 49     {
 50         if(q[i].opt==1)
 51         {
 52             if(!vis[q[i].ch]) vis[st[++top]=q[i].ch]=true;
 53             else return true;
 54         }
 55         else
 56         {
 57             if(!top) return true;
 58             else vis[st[top--]]=false;
 59         } 
 60     }
 61     return top!=0;
 62 }
 63 int get()
 64 {
 65     int now=0,ans=0;
 66     int stop=0;//这里x>y,要把栈弹到这里才能继续执行 
 67     for(int i=1;i<=len;i++)
 68     {
 69         if(q[i].opt==1)
 70         {
 71             int del=q[i].y-q[i].x;
 72             if(stop) ++top;
 73             else if(del<0) stop=++top;
 74             else if(del<=100) ++top;
 75             else now++,ans=max(ans,now),flag[++top]=true;
 76         }
 77         else
 78         {
 79             if(flag[top]) now--,flag[top]=false;
 80             if(stop&&stop==top) stop=0;
 81             top--;
 82         }
 83     }
 84     return ans;
 85 }
 86 void work()
 87 {
 88     clear(); cin>>len; fzd=getfzd();
 89     for(int i=1;i<=len;i++)
 90     {
 91         char c[5]; scanf("%s",c);
 92         if(c[0]=='F')
 93         {
 94             q[i].opt=1;
 95             scanf("%s",c); q[i].ch=c[0]-'a';
 96             q[i].x=read(); q[i].y=read();
 97         }
 98         else q[i].opt=2;
 99     }
100     if(judge()) {printf("ERR\n");return;}
101     maxn=get(); printf(maxn==fzd?"Yes\n":"No\n");
102 }
103 int main()
104 {
105     scanf("%d",&T);
106     while(T--) work();
107     return 0;
108 }

 

转载于:https://www.cnblogs.com/Slrslr/p/9588212.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值