时间复杂度 NOIP_2017_D1T2
有的题做了很久\感想比较深\可以引申很多\上台讲过,所以单开一篇,不放在总结下面。
这道题做的时候花了很长时间,犯的错也比较典型,当时写过一篇单独的总结,放在学校了,返校后粘上来。
时间复杂度
小明正在学习一种新的编程语言 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
, 其中 ii 是一个小写字母(保证不为 nn ),表示新建的变量名, x 和 y 可能是正整数或 n ,已知若为正整数则一定小于 100。
程序行若以E
开头,则表示循环体结束。
模拟题。
多组数据,要记得清空数组。
首先读入行数以及std的时间复杂度。
第一次做的时候发现std的复杂度可能不是一位数,然而还是处理错了,最坑的是对于小数据的处理是完全没有问题的,只有在数据达到一定程度时才能看出来,所以以后编程时写好一部分就要先测试,比如说这道题的std,编写完就应该测试各种情况如O(1),O(n^1),O(n^99)之类的情况,而不是等全写完了之后再改,很容易出错。一开始写的两位数处理中十位和个位是反的。。。。。。
正确的代码如下:
接着读入程序的每一行,先判断是否有语法错误,这一块感觉很难,其实却是最简单的部分。
- 变量冲突:维护一个栈,存放目前每一层的循环变量,当循环结束时将本层的循环变量销毁。如果某个变量当前正在被使用,又有新的变量要用同样的变量名,这个程序就出现了语法错误。
- 开始与结束不匹配:每读到一个F开头的句子,栈的深度+1,读到E开头的句子,深度-1。如果深度在某一次被减到<0了,证明语法错误,如果程序结束了深度却不为0,也是错的。
最后再计算时间复杂度。
这一块是最复杂的,每一层的时间复杂度等于本层的复杂度加上下一层中复杂度最大的一个,在dep层结束时再更新dep+1层的复杂度,否则会出错,注意,如果本层根本就不执行,它的时间复杂度一定是0,而不能再加上下一层的复杂度。这一部分其实一开始也想到了,但是改着改着就给忘了,以后做这种大模拟如果想到什么细节就写在纸上,到最后提交前再检查一下,因为边写边改的话过一会就忘了这一句有什么用,可能不小心就删了。
现在就只剩下计算本层的时间复杂度了。
除去循环变量和F,开始和结束共有9种情况:
F |
i |
n |
n |
|||||
F |
i |
n |
1 |
|||||
F |
i |
n |
1 |
2 |
||||
F |
i |
1 |
n |
|||||
F |
i |
1 |
1 |
|||||
F |
i |
1 |
1 |
2 |
||||
F |
i |
1 |
2 |
n |
||||
F |
i |
1 |
2 |
1 |
||||
F |
i |
1 |
2 |
1 |
2 |
如果是n,就用-1表示。
如果be和en相等,常数复杂度;
如果be是n,en是常数,不执行;
如果en是常数,be是n,n的复杂度;
如果en和be都是常数:be<=en,常数复杂度;
如果be>en,不执行。
# include <cstdio>
# include <iostream>
# include <cstring>
# include <cstring> using namespace std; int t,len,nl,Std,dep;
string st,pr[];
bool uke,f,vis[]={};
int sta[],maxa[];
int ans[],F[]; void ac()
{
for (int i=;i<=len;i++)
{
if(pr[i][]=='F')
{
dep++;
sta[dep]=pr[i][]-'a';
if (vis[sta[dep]]) uke=true;
vis[sta[dep]]=true;
}
else
{
if(dep==) uke=true;
vis[sta[dep]]=false;
dep--;
}
}
if(dep!=) uke=true;
return ;
} bool wa()
{
memset(maxa,,sizeof(maxa));
string no;
int be,en;
for (int i=;i<=len;i++)
{
if(pr[i][]=='F')
{
dep++;
no=pr[i];
int ss=;
if(no[]=='n')
{
be=-;
if(no[]=='n') en=-;
else if(no[]>=''&&no[]<='') en=(no[]-'')*+no[]-'';
else en=no[]-'';
}
else if(no[]==' ')
{
be=no[]-'';
if(no[]=='n') en=-;
else if(no[]>=''&&no[]<='') en=(no[]-'')*+no[]-'';
else en=no[]-'';
}
else
{
be=(no[]-'')*+no[]-'';
if(no[]=='n') en=-;
else if(no[]>=''&&no[]<='') en=(no[]-'')*+no[]-'';
else en=no[]-'';
}
if(be==en)
ss=;
else if(be==-)
ss=-;
else if(en==-)
ss=;
else if(be<=en)
ss=;
else
ss=-;
ans[dep]=ss;
}
else
{
if(ans[dep]!=-) ans[dep]+=maxa[dep];
maxa[dep-]=max(maxa[dep-],ans[dep]);
ans[dep]=;
maxa[dep]=;
dep--;
}
}
if(maxa[]==Std) return true;
return false;
} int main()
{
scanf("%d",&t);
for (int shzr=;shzr<=t;shzr++)
{
scanf("%d",&len);
getline(cin,st);
if(st[]=='') Std=;
else
{
if(st[]==')') Std=st[]-'';
else Std=(st[]-'')*+st[]-'';
}
memset(vis,,sizeof(vis));
memset(ans,,sizeof(ans));
memset(F,,sizeof(F));
uke=f=false;
for (int i=;i<=len;i++)
getline(cin,pr[i]);
dep=;
ac();
if(uke) printf("ERR\n");
else
{
dep=;
if(wa()) printf("Yes\n");
else printf("No\n");
}
}
return ;
}
时间复杂度
终于写完啦qwq。
---shzr
时间复杂度 NOIP_2017_D1T2的更多相关文章
- 时间复杂度分别为 O(n)和 O(1)的删除单链表结点的方法
有一个单链表,提供了头指针和一个结点指针,设计一个函数,在 O(1)时间内删除该结点指针指向的结点. 众所周知,链表无法随机存储,只能从头到尾去遍历整个链表,遇到目标节点之后删除之,这是最常规的思路和 ...
- 斐波拉契数列加强版——时间复杂度O(1),空间复杂度O(1)
对于斐波拉契经典问题,我们都非常熟悉,通过递推公式F(n) = F(n - ) + F(n - ),我们可以在线性时间内求出第n项F(n),现在考虑斐波拉契的加强版,我们要求的项数n的范围为int范围 ...
- C语言数组实现约瑟夫环问题,以及对其进行时间复杂度分析
尝试表达 本人试着去表达约瑟夫环问题:一群人围成一个圈,作这样的一个游戏,选定一个人作起点以及数数的方向,这个人先数1,到下一个人数2,直到数到游戏规则约定那个数的人,比如是3,数到3的那个人就离开这 ...
- 实现一个 能在O(1)时间复杂度 完成 Push、Pop、Min操作的 栈
一,问题描述 实现一个栈(元素遵守先入后出顺序),能够通过 min 方法在 O(1)时间内获取栈中的最小元素.同时,栈的基本操作:入栈(Push).出栈(Pop),也是在O(1)时间内完成的. 二,问 ...
- 设计一个Stack,要求Push、Pop、获取最大最小值时间复杂度都为O(1)
面试的时候,面试官让设计一个栈,要求有Push.Pop和获取最大最小值的操作,并且所有的操作都能够在O(1)的时间复杂度完成. 当时真没啥思路,后来在网上查了一下,恍然大悟,只能恨自己见识短浅.思路不 ...
- Linux内核完全注释阅读笔记1:O(1)时间复杂度查找timeout定时器
前言 一直有Linux kernel情节,之前也一直在看Linux kernel相关的书和代码,但是每次到最后又由于兴趣转变而荒废了.这次终于静下心来想把Linux内核相关的代码好好看看,算是对自己的 ...
- 数据结构(C语言第2版)----时间复杂度和单链表
马上要到校招了,复习下相关的基础知识. 时间复杂度是什么? 官方解释: 算法的执行时间需要依据算法所编制的程序在计算机上于运行时所消耗的时间来度量.在算法中可以使用基本的语句的执行次数作为算法的时间复 ...
- 时间复杂度---我又要想起初中数学老师的脸了xxxxx
时间复杂度: 常用的时间复杂度有:常数级,对数级,线性级 线性对数级 平方级,立方级别,多项式级别,指数级别,阶乘级别 这里我们主要探讨对数级,线性级,平方级,指数级---为什么不讨论其他的?别的我也 ...
- 【编程题目】如何对n个数进行排序,要求时间复杂度O(n),空间复杂度O(1)
转自:http://blog.csdn.net/vast_sea/article/details/8167968 看上去似乎任何已知的算法都无法做到,如果谁做到了,那么所有的排序方法:QuickSor ...
随机推荐
- Java中接口的特点
Java接口在1.8之后发生了重大变化.所以谈Java接口特点可以分为1.8版本之前和1.8版本之后. 1.8版本之前的特点: 接口里只能有静态全局常量和public修饰的抽象方法. 为了代码简洁,在 ...
- EL表达式无法获取Spring MVC的Model封装好的数据解决方法
1.在spring-mvc的配置文件中已经配置jsp的视图解析器 2.在Controller中使用Model的addAttribute方法添加属性name,msg 3.在jsp页面中使用${msg}取 ...
- JDBC使用DBUtils
1.commons-dbutils commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的简单封装,学习成本极低,并且使用dbutils能极大简化jd ...
- 编译gRPC Go版本使用的 ProtoBuffer 文件
本篇文章主要解决mac下安装ProtoBuffer,编译go版本gRPC用的.proto文件 安装 protoc 注意,gRPC 需要用到 proto3, 而目前 Release 的版本是 2.6.1 ...
- spring 中 InitializingBean 接口使用理解
前言:这两天在看 spring 与 quart 的集成,所以了解到 spring 是如何初始化 org.springframework.scheduling.quartz.SchedulerFacto ...
- Yarn vs npm:你需要知道的一切(转)
转载:https://zhuanlan.zhihu.com/p/23493436 原文链接:Yarn vs npm: Everything You Need to Know Facebook.Goog ...
- Vue 基本指令和html常用标签结合使用综合案例(含代码)
最近项目中要开发一个OA审批:里边涉及到流程跳转(流程较多),具体方案有:直接下一步,选择参与人或者选择某一个流程之后再选择参与人: 我们前端是APiCloud开发,这里我主要使用Vue来实现,把实现 ...
- lua模块化
main.lua local main = require("my") main.greeting() my.lua local foo = {} local function g ...
- js dictionary字典 遍历
var dic={A:"AA",B:"BB",C:"CC"} //不能length去for循环(length:undefined) dic[ ...
- Ajax 与 JSON
Ajax,是对Asynchronous JavaScript + XML的简写.这一技术能够向服务器请求额外的数据而无需卸载页面,会带来更好的用户体验. Ajax的核心是XMLHttpRequest对 ...