Luogu 3952(NOIP2017 D1T2 时间复杂度)(模拟+栈)

本文介绍了一种使用栈模拟简化代码的方法,用于计算代码复杂度,判断语法错误并验证给定复杂度的准确性。文章详细解释了处理平行循环和未进入循环的难点,提供了一个具体的实现方案。

传送门

题意:

给你T组简化代码,每组L行,给一个复杂度。模拟循环,计算复杂度,判断语法是否有误以及给定复杂度是否正确。

 

题解:

略(用栈模拟整个过程),方法基本就这一个,具体实现方法千变万化(代码中有注释)

 

本题大概有两大难点:

①同一层中可能有若干个平行的循环(如样例第五个程序),实际复杂度应取其中最大复杂度

②对于没有进入的循环不能直接跳过不处理(因为后面出现的语法错误也算数),后面退到当前循环中要特判(这也是要开第三个栈sa的原因)

 

注意:

①建议把题目中关键信息复制到代码头或一个单独文本中,边写边比对

②读入的复杂度和变量值可能不是一位数

③语法错误1可能不仅是F多了,也可能使E多了

④读入可用getline,也可用变形的读入优化(具体见代码)

 

至此NOIP2017全部AC,虽然现在不一定都能做但至少都自己AC过一遍,这一刻来得虽然稍微晚了一丢丢,但还是很有纪念意义。任重而道远,同志仍须努力!祝NOIP 2018 rp++!

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
const int INF=0x3f3f3f3f; 
inline int read() {
	int x=0;char c=getchar();
	while (c<'0'||c>'9') {if (c=='n') return INF;c=getchar();}
	while (c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
	return x;
}
bool ve[26];//变量名是否存在
int step;//当前循环层数
int hisans;//给定复杂度
bool gram;//语法错误
int numline;//程序行数
stack<char > sv;//当前层变量名
stack<int > sc;//当前层复杂度
stack<int > sa;//当前是否有效进入循环
int c[52];//各层实际复杂度
inline void smax(int &x,int y) {
	x=max(x,y);
}
void clean() {
	memset(ve,false,sizeof(ve));
	memset(c,0,sizeof(c));
	gram=false;
	step=0;
	numline=read();
	while (!sv.empty()) sv.pop();
	while (!sc.empty()) sc.pop();
	while (!sa.empty()) sa.pop();
}
int main() {
//	freopen("P3952_.in","r",stdin);
	int kase=read();
	while (kase--) {
		clean();
		char his[10];
		scanf("%s",his);
		if (his[2]=='1') hisans=0;
		else {
			if (his[5]==')') hisans=his[4]-'0';
			else if (his[6]==')') hisans=(his[4]-'0')*10+his[5]-'0';
			else if (his[7]==')') hisans=(his[4]-'0')*100+(his[5]-'0')*10+his[6]-'0';
		}
 		for (int line=1;line<=numline;++line) {
			char fe;//'F' or 'E'?
			while (!isalpha(fe=getchar()));
			if (fe=='F') {//进循环体
				char ch;//当前变量名 
				while (!isalpha(ch=getchar()));
				if (ve[ch-'a']) gram=true;
				ve[ch-'a']=true;
				int x=read(),y=read();
				if (gram) continue;//语法错误则直接跳过
				++step;
				if (x>y) {
					sv.push(ch);
					sc.push(0);
					sa.push(false);
				} else if (x==y) {
					sv.push(ch);
					sc.push(0);
					sa.push(true);
				} else if (x<y) {
					if (y==INF) {
						sv.push(ch);
						sc.push(1);
						sa.push(true);
					} else {
						sv.push(ch);
						sc.push(0);
						sa.push(true);
					}
				}
			} else {//出循环体
				if (sv.empty()) gram=true;
				if (gram) continue;//语法错误则直接跳过
				char nv=sv.top();sv.pop();
				ve[nv-'a']=false;
				int nc=sc.top();sc.pop();
				bool na=sa.top();sa.pop();
				int nxtc=c[step];
				c[step--]=0;
				if (na) smax(c[step],nc+nxtc);
			}
		}
		if (!sc.empty()) gram=true;
		if (gram) puts("ERR");
		else if (c[0]^hisans) puts("No");
		else if (c[0]==hisans) puts("Yes");
	}
	return 0;
}

 

### 关于NOIP 2017 测试数据下载 NOIP(全国青少年信息学奥林匹克联赛)作为国内重要的编程竞赛之一,其历年试题和测试数据对于参赛者具有很高的学习价值。然而,官方通常不会公开提供完整的测试数据集,因为这些数据主要用于评估选手程序的正确性和性能。 #### 官方资源获取方式 中国计算机学会(CCF)是NOIP赛事的主办方,虽然他们并未直接开放所有测试数据供公众下载,但可以通过以下途径获得部分资料: - **官方网站**:访问 CCF 的官网[^6],查看是否有相关公告或文件发布。 - **历届真题解析**:一些第三方机构会整理并分享 NOIP 近年的题目及其解答思路,尽管不包含原始测试数据,但仍有助于理解命题方向和解法技巧[^7]。 #### 第三方平台推荐 由于正式渠道受限,在实际操作中许多教练员与学生会选择借助社区力量来补充练习素材: - **洛谷 (Luogu)**: 此网站收录了大量的OI/ACM类问题,其中包括多个版本的NOIP赛题重制版。用户可以在线提交代码并通过系统评测得到反馈结果[^8]。 - **Codeforces Gym**: 虽然主要面向国际比赛,但也存在由个人上传的针对特定区域赛事的专项训练包,其中可能涉及到了NOIP相关内容[^9]。 需要注意的是,从非授权来源下载敏感材料可能存在版权风险或其他隐患,因此建议优先考虑合法合规的方法来进行准备活动。 ```cpp // 示例:如何验证自己的解决方案是否满足给定条件? #include <bits/stdc++.h> using namespace std; int main(){ long long n,m; cin>>n>>m; vector<long long> books(n); for(auto &x :books){ cin >> x; } string complexity; getline(cin,complexity); // 获取时间复杂度表达式 bool isValidFormat=true; try{ regex re("O\\(.*?\\)"); smatch match; if(!regex_match(complexity,match,re)){ throw invalid_argument("Invalid format"); } // 更复杂的逻辑处理... }catch(const exception& e){ cout << "ERR\n"; return 0; } // 计算具体数值并与预期比较省略... return 0; } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值