洛谷 P3952 时间复杂度 解题报告

P3952 时间复杂度

题目描述

小明正在学习一种新的编程语言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 \le 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\)

数据规模与约定

对于\(30\%\)的数据:不存在语法错误,数据保证小明给出的每个程序的前\(L/2\)行一定为以\(F\)开头的语句,第\(L/2+1\)行至第\(L\)行一定为以\(E\)开头的语句,\(L \le 10\),若\(x\)\(y\)均为整数,\(x\)一定小于\(y\),且只有\(y\)有可能为\(n\)

对于\(50\%\)的数据:不存在语法错误, \(L \le 100\),且若\(x\)\(y\)均为整数,\(x\)一定小于\(y\), 且只有\(y\)有可能为\(n\)

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

对于\(100\%\)的数据: \(L \le 100\)


今天晚上写了好久,还重构了一次代码,考场上估计会凉。

写模拟题的技巧:

  1. 先在纸上写好流程和细节,最后再动手
  2. 多使用函数完成功能,使结构清晰

Code:

#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int N=205;
const int inf=0x3f3f3f3f;
int used[N];//维护字母使用
struct node
{
    int fzd,var;
}S[N];
int tot,n,t,err,fzd,fzd0,ans;
string s;
int read_var()//读取变量
{
    cin>>s;
    if(used[s[0]]) err=1;
    used[s[0]]=1;
    return s[0];
}
int read_num()//读取数字0
{
    cin>>s;
    if(s[0]=='n') return inf;
    int x=0;
    for(int i=0;i<s.size();i++)
        x=(x<<3)+(x<<1)+s[i]-'0';
    return x;
}
int read_fzd()//读取复杂度
{
    int a=read_num(),b=read_num();
    if(a!=inf&&b==inf) return 1;
    if(a>b) return -inf;
    return 0;
}
void read()//读入一整行
{
    cin>>s;
    if(s[0]=='F')
    {
        S[++tot].var=read_var();//读取变量
        S[tot].fzd=read_fzd();//读取复杂度
        fzd+=S[tot].fzd;//处理复杂度
        ans=max(fzd,ans);//更新复杂度
    }
    else
    {
        if(!tot) {err=1;return;}//层数错误
        used[S[tot].var]=0;//取消变量使用
        fzd-=S[tot--].fzd;//还原复杂度
    }
}
void read_initfzd()//读取初始复杂度
{
    cin>>s;
    if(s[2]=='1') return;
    for(int i=4;s[i]!=')';i++)
        fzd0=(fzd0<<3)+(fzd0<<1)+s[i]-'0';
}
void init()
{
    memset(used,0,sizeof(used));
    ans=fzd=fzd0=tot=err=0;
}
void work()
{
    scanf("%d",&n);
    read_initfzd();
    for(int i=1;i<=n;i++)
        read();
    if(tot||err) printf("ERR\n");
    else if(fzd0==ans) printf("Yes\n");
    else printf("No\n");
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        init();
        work();
    }
    return 0;
}


2018.7.26

posted @ 2018-07-26 21:39  露迭月  阅读(434)  评论(0编辑  收藏  举报