• 洛谷 P3952 [NOIP2017 提高组] 时间复杂度


    Description

    P3952 [NOIP2017 提高组] 时间复杂度

    Solution

    膜你模拟

    这题很久之前刚开始学 (OI) 的时候做过一次,当时着实被虐了好几个小时才做出来,还是看了题解的。

    于是怀恨在心,总之现在来复盘一下,感觉还可以,多想想,细节也不算太多。

    emm没什么好说的了,直接看代码吧(有注释)。

    Code

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int T, l;
    char o[1000];
    int stk[110], top, maxt, tim, flag, t;
    //stk:记录每一层循环能否进入,且是否贡献复杂度。 1:能进入但不贡献复杂度		2:不能进入		3:能进入且贡献复杂度	top:栈顶
    //maxt:记录最终出的时间复杂度。(max{tim})
    //tim:可能存在并列的循环,所以记录每一时刻的时间复杂度
    //flag:是否有编译错误。
    //t:题目中输入的时间复杂度。
    char op, x, a[10], b[10];
    //输入的4个变量。
    int tc[110];
    //和栈同时更新,记录每一层循环的变量是多少。
    bool vis[30];
    //桶,用来快速判断一个变量是否被用过。
    
    int zs(char c[]){//把 F i x y 中的 x 和 y 提取出来,判断能否进入这个循环
    	if(strlen(c) == 1) return c[0] - '0';
    	else return 10 * (c[0] - '0') + (c[1] - '0');//小于100
    }
    
    void calc(){//把输入的复杂度提取出来,就是那个O(n^w)中的 w
    	if(o[2] == 'n'){
    		if(o[5] == ')') t = o[4] - '0';
    		else t = 10 * (o[4] - '0') + (o[5] - '0');//w < 100
    	}
    	else t = 0;//常数的话,复杂度为0
    }
    
    int main(){
    	scanf("%d", &T);
    	while(T--){
    		top = flag = maxt = tim = 0;//多测清空
    		memset(vis, 0, sizeof(vis));
    		memset(tc, 0, sizeof(tc));
    		cin >> l >> o;
    		calc();//计算输入的时间复杂度
    		for(int i = 1; i <= l; i++){
    			cin >> op;
    			if(op == 'F'){
    				cin >> x >> a >> b;
    				if(vis[x - 'a']){//如果当前变量被用过。
    					flag = 1;//编译错误
    					top++;//还得压栈,不然后面输入就乱了。
    					continue;
    				}
    				if(stk[top] == 2){//上一层循环无法进入
    					stk[++top] = 2;//传递标记
    					continue;
    				}
    				tc[++top] = x - 'a';//当前变量入栈
    				vis[x - 'a'] = 1;//给桶打上标记
    				if(a[0] != 'n' && b[0] != 'n'){//两个都是数字
    					if(zs(a) <= zs(b)) stk[top] = 1;//1:可以进入
    					else stk[top] = 2;//2:无法进入
    				}else{//有至少一个是n
    					if(a[0] != 'n' && b[0] == 'n') stk[top] = 3, tim++;//3: 复杂度+1 
    					if(a[0] == 'n' && b[0] != 'n') stk[top] = 2;
    					if(a[0] == 'n' && b[0] == 'n') stk[top] = 1;
    				}
    				maxt = max(maxt, tim);//更新复杂度最大值
    			}else{
    				if(!top){//栈已经空了,还在退出,直接编译错误
    					flag = 1;
    					continue;
    				}
    				if(stk[top] == 3) tim--;//判断对应循环是否贡献复杂度,如果贡献,tim--
    				vis[tc[top--]] = 0;//删去对应循环变量在桶中的标记
    				maxt = max(maxt, tim);//这个可以不写(好像)
    			}
    		}
    		if(flag || top || (l & 1)) puts("ERR");//编译错误(不完全)|| 桶中还有元素 || 输入长度为奇数
    		else if(maxt == t) puts("Yes");
    		else puts("No");
    	}
    	return 0;
    }
    

    End

    本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15173806.html

  • 相关阅读:
    MyEclipse 6.0.1 注册码过期后的解决办法
    .NET代码管理工具 Narrange
    oracle 测试代码
    log4net for web快速入门
    Sql 2005 千万级数据库IO规划
    VSS Internet Access Configuration [转贴]
    开车二十年后得到的真实的26条教训!开车的人一定看看!&not;
    在 IIS 6.0 中以编程方式管理服务器证书
    ASP.NET页面刷新的实现方法(Zt)
    服务器处理器一览
  • 原文地址:https://www.cnblogs.com/xixike/p/15173806.html
Copyright © 2020-2023  润新知