这是一道很烦人的模拟题。
特别考验代码能力,特别墨迹,特别恶心。
不是题恶心,是写起来很恶心。
先看题吧。
题目
题目描述
小明正在学习一种新的编程语言 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。
输入输出样例
输入样例:
82 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
输出样例
YesYes
ERR
Yes
No
Yes
Yes
ERR
说明
输入输出样例解释
第一个程序 i从1到1是常数复杂度。第二个程序 x从1到 n是 n的一次方的复杂度。
第三个程序有一个 F开启循环却没有 E结束,语法错误。
第四个程序二重循环, n的平方的复杂度。
第五个程序两个一重循环, n的一次方的复杂度。
第六个程序第一重循环正常,但第二重循环开始即终止(因为 n远大于100,100大于4)。
第七个程序第一重循环无法进入,故为常数复杂度。
第八个程序第二重循环中的变量x与第一重循环中的变量重复,出现语法错误②,输出 ERR。
数据规模与约定
对于 30%的数据:不存在语法错误,数据保证小明给出的每个程序的前 L/2行一定为以 F开头的语句,第 L/2+1行至第 L行一定为以 E开头的语句, L≤10,若 x、 y均为整数, x一定小于 y,且只有 y有可能为 n。对于 50%的数据:不存在语法错误, L≤100,且若 x、 y均为整数, x一定小于 y,且只有 y有可能为 n。
对于 70%的数据:不存在语法错误, L≤100。
对于 100%的数据: L≤100。
分析
裸模拟。
一共可以分三步。
先读入这是一定的。
先判断语法错误,如果有直接
ERR走人啦
。
然后计算复杂度,符合
Yes,不符合
No。
剩下的就是调试啦。
上代码
这道题花了一天啊啊啊啊啊。
(一如既往的独特码风)
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <iostream>
#include <queue>
#include <vector>
#define N 110
using namespace std;
int n;
int m;
int i=1;
int ans=0;
int flag=1;
int bz[N+N];
char s[N];
int get()
{
char c;
c=getchar();
int x;
x=0;
if(c=='n')
{
getchar();
return -1;
}
for(;c>='0'&&c<='9';c=getchar())
x=x*10+c-48;
return x;
}
void dg(int x)
{
int aans;
int hy;
hy=ans;
aans=ans;
while(i<=n)
{
i++;
char c;
c=getchar();
if(c=='E')
{
scanf("\n");
ans=aans;
return;
}
scanf(" %c ",&c);
if(bz[c]==1)
flag=0;
bz[c]=1;
int q;
int w;
q=get();
w=get();
if(q==-1&&w==-1)
dg(x+1);
if(q==-1&&w>0)
{
int jy=ans;
dg(x+1);
ans=jy;
}
if(q>0&&w==-1)
{
ans++;
dg(x+1);
}
if(q>0&&w>0)
{
int jy=-1;
if(q>w)
jy=ans;
dg(x+1);
if(jy!=-1)
ans=jy;
}
bz[c]=0;
aans=max(ans,aans);
ans=hy;
}
ans=aans;
if(i>n&&x!=0)
flag=0;
}
int main()
{
int ac;
scanf("%d\n",&ac);
for(;ac;ac--)
{
memset(bz,0,sizeof(bz));
i=1;
flag=1;
ans=0;
char c;
scanf("%d O(%c",&n,&c);
if(c=='n')
scanf("^%d",&m);
else
m=0;
scanf(")\n");
dg(0);
if(i<=n)
{
flag=0;
while(i<=n)
{
char c;
c=getchar();
if(c=='E')
scanf("\n");
else
{
scanf(" %c ",&c);
int q;
q=get();
q=get();
}
i++;
}
}
if(flag==0)
printf("ERR");
else
{
if(ans==m)
printf("Yes");
else
printf("No");
}
printf("\n");
}
return 0;
}
PS
1.格式化输入流函数“
scanf”可以读入指定内容,我的代码里这点应用的很多。
2.写不明白
scanf推荐使用
cin,简单到爆(时间什么的就不计了吧数据太小)。
3.我用的递归,当然各种方法都可以因为递归太抽象了啊哈哈哈。