时间复杂度 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 ...
随机推荐
- C# 分页方法
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Web; ...
- 啰里吧嗦redis
1.redis是什么 redis官网地址 Redis is an open source (BSD licensed), in-memory data structure store, used as ...
- FastJson的忽略字段和格式日期用法
1.指定序列化顺序 缺省fastjson序列化一个java bean,是根据fieldName的字母序进行序列化的,你可以通过ordinal指定字段的顺序.这个特性需要1.1.42以上版本. pub ...
- MySQL 报错
SELECT COUNT(1) FROM (select tid from teacher where tname like '李%') 1248 - Every derived table must ...
- Code Signal_练习题_reverseParentheses
You have a string s that consists of English letters, punctuation marks, whitespace characters, and ...
- ECMAScript 5和ECMAScript6的新特性以及浏览器支持情况
ECMAScript简介: 它是一种由Ecma国际(前身为欧洲计算机制造商协会)制定和发布的脚本语言规范,javascript在它基础上经行了自己的封装.但通常来说,术语ECMAScript和java ...
- DotNetBar的使用—(界面风格)
C# WinForm项目中自带的窗体风格很普通,一点都不美观.DotNetBar就是一套.NET美化控件库,有70几个控件以及多种界面的皮肤风格.关于控件的效果在官网上进行查看http://www.d ...
- 洛谷P4360 [CEOI2004]锯木厂选址(dp 斜率优化)
题意 题目链接 Sol 枚举第二个球放的位置,用前缀和推一波之后发现可以斜率优化 // luogu-judger-enable-o2 #include<bits/stdc++.h> #de ...
- Csv读写类
<?php /** * CSV 文件读写类 * * 示例: $header = array('name' => '名字', 'age' =>'年龄', 'idcard' => ...
- js下载文件
本文的前提是:后台给的是一个可以下载的url的情况下的下载: 怎样的文件url才能触发浏览器的下载行为?(转自SF) 能触发浏览器下载的url有两类: response header中指定了Conte ...