[NOIp 2017] 时间复杂度

洛谷 3952

输入一整行字符串时,如果中间有空格,则不能用 scanf("%s",...) 来输入!
scanf() 会在空格处停下!

在NOIp2018 前夕终于做出了NOIp2017的题

Candy? 说这道题用栈做,其实完全可以不用栈我不会,于是用一个比较笨拙的方法:找出与每个F配对的E,然后从第一个循环开始处理。

利用循环结构处理并列的FE,递归处理嵌套的FE

用一个集合记录变量的名字,当遇到一个新变量名字时,查询是否冲突,一个循环结束改后,及时删除这个变量名。

第一次提交时只有 37 分,输出中间结果发现 match 过程中出现问题。。。冥思苦想好久不得其解,往上一翻翻然醒悟:

match 数组应该开 MAXL=100+10 的大小,结果写成了int match[MAXN] ,只开了 20 。。。

写程序时一定要细心!!!不能再犯这种低级错误!!!

//Copyright(C)Corona.
//2018-10-29
#include <set>
#include <stack>
#include <string>
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int MAXL=100+10,MAXN=20;
char p[MAXL][MAXN];
int match[MAXL];
set<string> var;

inline void scanf(char cache[],char End,int maxn) {
    for(int i=0; i<maxn; i++) {
        char c=getchar();
        if(c==End || c=='\0') {
            cache[i]='\0';
            return;
        } else {
            cache[i]=c;
        }
    }
    cache[maxn]='\0';
}

inline void scanf(int& x,char str[]) {
    x=0;int len=strlen(str),f=0;
    for(int i=0;i<len;i++) {
        if(str[i]<'0' || str[i]>'9') {
            if(str[i]=='^') f=1;
        } else {
            x=x*10+str[i]-'0';
        }
    } x*=f;
}

inline void Match(int L,int& err) {
    memset(match,-1,sizeof(match));
    for(int i=0; i<L; i++)
        if(p[i][0]=='F') {
            int cf=1;
            for(int j=i+1; j<L; j++) {
				cf += (p[j][0]=='F'?1:-1);
                if(!cf) {
                    match[i]=j;
                    break;
                }
            }
        }
}

inline void getName(char pro[],string& name,string& from,string& to) {
    int l=strlen(pro),cnt=0;
    char a[3][MAXN];
    for(int i=0; i<l; i++) {
        if(pro[i]==' ') {
            cnt++;
            for(int j=i+1,k=0; j<=l; j++,k++) {
                a[cnt-1][k]=pro[j];
                if(pro[j]==' ' || pro[j]=='\0' || j==l) {
                    a[cnt-1][k]='\0';
                    break;
                }
            }
        }
    }
    name=a[0];from=a[1];to=a[2];
}
inline int num(string& s) {
    int n=0;
    for(int i=0,m=s.length(); i<m; i++) {
        n=n*10+s[i]-'0';
    }
    return n;
}
inline int solve(int start,int end,int& err) {
    int init,in_loop=1;
    string name,from,to;
    if(start == -1) {
        //初始化为O(1)
        init=0;
    } else {
        //初始化为当前 F 循环的复杂度
        getName(p[start],name,from,to);
        if(var.count(name)) {
            err=5;
        } else {
            var.insert(name);
        }

        if(from=="n" && to=="n") {
            init=0;
        } else if(from=="n" && to!="n") {
            init=0;
            in_loop=0;//未进入循环
        } else if(from!="n" && to=="n") {
            init=1;
        } else {
            init=0;
            if(num(from)>num(to)) in_loop=0;
        }
    }

    int inc=0;//初始化为O(1)
    for(int i=start+1; i!=end; i++) {
        if(p[i][0]=='F') {
            inc=max(inc,solve(i,match[i],err));
            i=match[i];
        }
    }
    var.erase(name);
    return in_loop==1?init+inc:0;
}

int main() {
    int T;
    cin>>T;
    while(T--) {
        int L;
        cin>>L;
        char his_ans[MAXN];
        scanf(his_ans,'\n',MAXN);
        int complexity,com=0;
        scanf(complexity,his_ans);
        int err=0,cnt=0;
        for(int i=0; i<L; i++) {
            scanf(p[i],'\n',MAXN);
            if(p[i][0]=='F') cnt++;
            else if(p[i][0]=='E') cnt--;
            if(cnt<0) {
                err=1;
            }
        }
        if(cnt!=0) err=2;
        else {
            Match(L,err);
            com=solve(-1,L,err);
        }
        if(err) {
            printf("ERR\n");
        } else {
            if(com==complexity) {
                printf("Yes\n");
            } else {
                printf("No\n");
            }

        }
    }
    return 0;
}
posted @ 2018-10-29 23:46  昤昽  阅读(188)  评论(0编辑  收藏  举报