传送门
题意:
给你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