NOIP2017 D1T2 时间复杂度

迟到了近一年的题解。。。(好吧其实只是我现在才敢做,没想到1A)

首先不要在线判断,先把代码一行一行给读下来再慢慢判断。
对于每层循环,用栈存下来,同时记录一个flag数组判断当前循环情况:

  • 1表示该层循环有效
  • 0表示当前循环是常数循环,不影响后面循环
  • -1表示当前循环to < from,不能进入

剩下的差不多都在代码注释里了。。(代码巨丑)

#include <cstdio>
#include <algorithm>
using namespace std;

int main(){
	freopen("in.txt", "r", stdin);
	int T;
	scanf("%d", &T);
	while(T--){
		char s[200];
		int L;
		
		scanf("%d%s", &L, s);
		
		
		int w = 0; //时间复杂度 
		if(s[2] == 'n'){
			int i = 4;
			while(s[i] >= '0' && s[i] <= '9'){
				w = w*10 + s[i] - '0'; i++; //改编自读入优化 
			}
		}
		else{
			w = 0; //n^0 即常数复杂度 
		}
//		printf("w = %d\n", w);
		
		char sta[100]; int top = 0;//栈 
		int ans = 0; //储存答案 
		int flag[100] = {0}; //标记当前层是有效循环或无效循环 
		bool pd[30] = {false}; //变量判重
		bool ERR = false; //判断ERR 
		
		for(int i = 1; i <= L; i++){
//			printf("!");
			scanf("%s", s);
//			printf("%s ", s);
			if(s[0] == 'F'){ //循环开始 
				char v[10]; //该变量
				scanf("%s", v);
//				printf("%s ", v);
				sta[++top] = v[0];
				
				if(pd[v[0] - 'a'] == true){
					ERR = true;
//					printf("----------pdERR\n");
				}
				else pd[v[0] - 'a'] = true;
				
				int from = 0, to = 0;
				char s1[10], s2[10];
				scanf("%s %s", s1, s2);
				
				if(s1[0] == 'n'){
					from = 99999; //将n标记为99999,方便下面判断 
				}
				else{
					int j = 0;
					while(s1[j] >= '0' && s1[j] <= '9'){
						from = from*10 + s1[j] - '0'; j++;
					}
				}
				
				if(s2[0] == 'n'){
					to = 99999;
				}
				else{
					int j = 0;
					while(s2[j] >= '0' && s2[j] <= '9'){
						to = to*10 + s2[j] - '0'; j++; 
					}
				}
				
//				printf("%d %d", from, to);
				
				if(to < from){ //无效循环 
//					printf("top = %d\n", top);
					flag[top] = -1; //无效循环
//					printf("%d\n", flag[top]);
				}
				else if(to - from < 1000) //能进入循环,但不影响时间复杂度 
					flag[top] = 0;
				else if(to - from >= 1000){ //进入循环,影响时间复杂度 
					flag[top] = 1;
					int k = 1, tmp = 0;
					while(k <= top && flag[k] != -1) //每次更新实际复杂度 
						tmp += flag[k++];
//					printf("flag1 = %d\n", flag[1]);
//					printf("top = %d, tmp = %d\n", top, tmp);
					ans = max(ans, tmp);
				}
			}
			else if(s[0] == 'E'){
				pd[sta[top] - 'a'] = false; 
				top--;
				if(top < 0){
					ERR = true; //栈空出栈,ERR 
//					printf("----------staERR\n");
				}
			}
//			printf("\n");
		}
		
		if(top > 0) ERR = true; //结束时若top > 0 说明循环体未结束 
		
		if(ERR) puts("ERR"); //发生错误 
		else if(w == ans) puts("Yes"); //与目标复杂度匹配 
		else puts("No"); //不匹配 
//		printf("\n");
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值