1 条题解
-
0
自动搬运
来自洛谷,原作者为

Oxygen_L
**搬运于
2025-08-24 21:35:23,当前版本为作者最后更新于2018-07-20 21:56:53,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
写在前面
实际上已近写过一篇这个题的题解了,这次只是稍作修改,压缩了以前又臭又长的代码,顺便再说明一下解题思路。
遇到的问题
一看这个题就知道是模拟,但是怎么模拟呢?
首先,读入与存储问题,如何准确的读入以及如何将输入的代码存起来。
其次,也是最难的,模拟程序运行,其中最关键的就是如何模拟循环的运行。
再者,计算器的问题,赋值语句与循环次数的计算。
解决方案
1.读入与存储,开一个二维的char数组(string也行,个人喜好),使用scanf("%s",s)读入,遇到空格跳过。
2.运行过程,其他语句不多说,就讲讲最关键的循环语句吧,看到有很多大佬都是用栈来模拟,个人不太习惯用栈模拟,于是用了类似于递归的方法,一层层进入,再退出。
3.有关计算器,由于题中给出了语句的执行次数的总和小于2000000次,那么计算器完全可以使用递归代替栈来写,并且完全不用担心会超时。
最后附上AC代码,代码中有解释
#include <cstdio> #include <iostream> #include <cstring> #include <string> #include <cmath> #include <algorithm> #define MAXN 1001 using namespace std; //函数总览,后面有解释 void read(); void work(); void find(); void write(char x[]); int check(char x[]); void run(char x[]); void pre(char x[],int l,int r); int calc(char x[],int l,int r); void run_loo(char x[]); int run_fu(char x[],int in,int enk); char str[MAXN][MAXN],s[MAXN]; int tot=0,h=1,f[MAXN],ff[MAXN],sh[30]; const int sta=1,en=2,loo=3,con=4,wri=5,bre=6,fu=7; //读入,处理掉空格 void read(){ while((scanf("%s",s))!=EOF){ if(s[0]!=' '){ strcpy(str[++tot],s); } } } //输出 void run_wri(char x[]){ ++h; printf("%d\n",run_fu(str[h],0,strlen(str[h])-1)); } //预处理,找到循环的开始与结束 void find(){ int v[MAXN],v1=0; for(int i=2;i<tot;i++){ if(check(str[i])==loo){ v1++; v[v1]=i; }else if(check(str[i])==en){ f[v[v1]]=i; v1--; } } } //循环语句的递归实现 void run_loo(char x[]){ ++h; int t=run_fu(str[h],0,strlen(str[h])-1),tmp=h-1; for(int i=1;i<=t;i++){ ++h; while(check(str[h])!=en){ if(check(str[h])==loo){ run_loo(x); }else if(check(str[h])==con){ break; }else if(check(str[h])==bre){ h=f[tmp]; return; } run(str[h]); ++h; } h=tmp+1; } h=f[tmp]; } //每次使用计算器之前的预处理,为了处理表达式中有括号匹配的情况 void pre(char x[],int l,int r){ int v[MAXN],tot=0; for(int i=l;i<=r;++i){ if(x[i]=='('){ v[++tot]=i; }else if(x[i]==')'){ ff[v[tot]]=i; --tot; } } } //递归实现简单计算器 int calc(char x[],int l,int r){ if(l==r&&x[l]>='a'&&x[l]<='z') return sh[x[l]-'a']; if(x[l]=='('&&x[r]==')'&&ff[l]==r){ return calc(x,l+1,r-1); } int jia=0,cheng=0,isjia=0,ischeng=0,fa=0,isfa=0; for(int i=l;i<=r;++i){ if(x[i]=='+') jia=i,isjia=1; else if(x[i]=='*') cheng=i,ischeng=1; else if(x[i]=='/') cheng=i,ischeng=0; else if(x[i]=='-') jia=i,isjia=0; else if(x[i]=='^') isfa=1,fa=i; else if(x[i]=='(') i=ff[i]-1; } if(jia!=0){ if(isjia==1) return (calc(x,l,jia-1)+calc(x,jia+1,r)); else return (calc(x,l,jia-1)-calc(x,jia+1,r)); }else if(cheng!=0){ if(ischeng==1) return (calc(x,l,cheng-1)*calc(x,cheng+1,r)); else return (calc(x,l,cheng-1)/calc(x,cheng+1,r)); }else if(isfa!=0){ return (int)pow(calc(x,l,fa-1)*1.0,calc(x,fa+1,r)*1.0); }else if(jia==0&&cheng==0&&isfa==0){ int tmp=0; for(int i=l;i<=r;++i){ tmp=(tmp*10+(x[i]-'0')); } return tmp; } } //赋值语句的运行,调用calc()函数计算 int run_fu(char x[],int in,int enk){ memset(ff,0,sizeof(ff)); pre(x,in,enk); int res=calc(x,in,enk); return res; } //判断是哪一种语句 int check(char x[]){ if(x[1]=='='){ return fu; }else if(x[0]=='s'){ return sta; }else if(x[0]=='e'&&x[1]=='n'){ return en; }else if(x[0]=='l'&&x[1]=='o'){ return loo; }else if(x[0]=='c'&&x[1]=='o'){ return con; }else if(x[0]=='w'&&x[1]=='r'){ return wri; }else if(x[0]=='b'&&x[1]=='r'){ return bre; }else{ return -1; } } //运行每一句语句 void run(char x[]){ int k=check(x); switch(k){ case 3:run_loo(x); break; case 5:run_wri(x); break; case 7:sh[x[0]-'a']=run_fu(x,2,strlen(x)-1); break; default:break; } } //循环每一句语句 void work(){ while(h<=tot){ run(str[h]); ++h; } } int main(){ read(); find(); work(); return 0; }有问题可在评论区留言哟。(●'◡'●)。~~~~~~~
- 1
信息
- ID
- 1228
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者