1 条题解

  • 0
    @ 2025-8-24 21:35:23

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar 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
    上传者