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

传送门

题意:

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

 

题解:

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

 

本题大概有两大难点:

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

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

 

注意:

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

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

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

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

 

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

#include
#include
#include
#include
#include
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 sv;//当前层变量名
stack sc;//当前层复杂度
stack 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

 

你可能感兴趣的:(杂题)