P3952 时间复杂度

出 现 了
简 单 % 你
这道题把我的毒瘤码风都逼出来了

这不就是道模拟吗!
我们用一个栈存已经使用的变量,用一个栈存这一层是否对复杂度有贡献,同时写一个skip函数,在出现循环不能进入的情况时强行跳过这一段代码
最后把复杂度算出来,对比就好了

变量解释:
code:每一行的代码
F:用于占位,内容一定为"F"
var:变量名
from:循环起始值
to:循环终值
v:每个变量是否被使用
vars:被使用的变量名栈
top:目前循环嵌套层数
n:剩余输入层数
O:小明算到的复杂度
now_comp:当前复杂度
st ed:循环始终值
n_const:记录这一层是否对复杂度增长有贡献

函数解释:
read(int&, char*)从字符串中读入数字,跳过特殊字符

inline void read(int &x, char *s) {
	x = 0;
	while(*s < 48 || 57 < *s) ++s;
	for(; 48 <= *s && *s <= 57; ++s) x = x * 10 + (*s & 15);
}

skip(int&, int&)跳过当前循环,并检测编译性错误

bool skip(int &n,int &top) {//把主函数里的n和top传进来,防止提前读到下一个点,还要维护已经使用的变量
//整个函数相当于一个微缩型的主函数
	const int last = top - 1;
	while(top != last && n--) {
		gets(code);
		if(*code == 'F') {//开启下一层循环
			sscanf(code, "%s%s%s%s", F, var, from, to);//从代码中读取变量等信息
			if(v[*var]) {
				while(n--) gets(code);
				puts("ERR");
				return 1;
			}
			v[*var] = 1;//标记变量使用
			vars.push(*var);//同上
			top++;
		}
		else {
			v[vars.top()] = 0;
			vars.pop();
			top--;
		}
	}
	return 0;
}

reset:每组数据的重置

void reset() {
	memset(v, 0, sizeof(v));
	while(vars.size()) vars.pop();
}

Main:主函数

void Main() {
	int n, O;
	scanf("%d%s\n", &n, code + 1);
	if(code[3] != 'n') O = 0;
	else read(O, code + 1);//读复杂度
	int now_comp = 0, ans = 0, top = 0;
	int st, ed;
	stack<int> n_const;
	while(n--) {
		gets(code);
		if(*code == 'F') {
			sscanf(code, "%s%s%s%s", F, var, from, to);
			if(v[*var]) {//变量冲突
				while(n--) gets(code);
				puts("ERR");
				return;
			}
			v[*var] = 1;
			vars.push(*var);
			top++;
			if(*from == 'n')
				if(*to == 'n')
					n_const.push(0);
				else {
					if(skip(n,top)) return;
				}
			else
				if(*to == 'n') {
					now_comp++;
					n_const.push(1);
				}
				else {
					read(st, from);
					read(ed, to);
					if(st > ed) {
						if(skip(n,top)) return;
					}
					else n_const.push(0);
				}
		}
		else {
			if(top == 0) {//E的个数比F还多
				while(n--) gets(code);
				puts("ERR");
				return;
			}
			ans = max(ans, now_comp);
			v[vars.top()] = 0;
			vars.pop();
			now_comp -= n_const.top();
			n_const.pop();
			top--;
		}
	}
	if(top)//E的个数不够
		puts("ERR");
	else if(ans != O)
			puts("No");
		else puts("Yes");
}

总代码:

#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
inline int max(const int a, const int b) {
	return a > b ? a : b;
}
inline void read(int &x, char *s) {
	x = 0;
	while(*s < 48 || 57 < *s) ++s;
	for(; 48 <= *s && *s <= 57; ++s) x = x * 10 + (*s & 15);
}
char code[1100];
char F[2], var[2], from[10], to[10];
char v[1 << 7];
stack<char> vars;
bool skip(int &n,int &top) {
	const int last = top - 1;
	while(top != last && n--) {
		gets(code);
		if(*code == 'F') {
			sscanf(code, "%s%s%s%s", F, var, from, to);
			if(v[*var]) {
				while(n--) gets(code);
				puts("ERR");
				return 1;
			}
			v[*var] = 1;
			vars.push(*var);
			top++;
		}
		else {
			v[vars.top()] = 0;
			vars.pop();
			top--;
		}
	}
	return 0;
}
void reset() {
	memset(v, 0, sizeof(v));
	while(vars.size()) vars.pop();
}
void Main() {
	int n, O;
	scanf("%d%s\n", &n, code + 1);
	if(code[3] != 'n') O = 0;
	else read(O, code + 1);
	int now_comp = 0, ans = 0, top = 0;
	int st, ed;
	stack<int> n_const;
	while(n--) {
		gets(code);
		if(*code == 'F') {
			sscanf(code, "%s%s%s%s", F, var, from, to);
			if(v[*var]) {
				while(n--) gets(code);
				puts("ERR");
				return;
			}
			v[*var] = 1;
			vars.push(*var);
			top++;
			if(*from == 'n')
				if(*to == 'n')
					n_const.push(0);
				else {
					if(skip(n,top)) return;
				}
			else
				if(*to == 'n') {
					now_comp++;
					n_const.push(1);
				}
				else {
					read(st, from);
					read(ed, to);
					if(st > ed) {
						if(skip(n,top)) return;
					}
					else n_const.push(0);
				}
		}
		else {
			if(top == 0) {
				while(n--) gets(code);
				puts("ERR");
				return;
			}
			ans = max(ans, now_comp);
			v[vars.top()] = 0;
			vars.pop();
			now_comp -= n_const.top();
			n_const.pop();
			top--;
		}
	}
	if(top)
		puts("ERR");
	else if(ans != O)
			puts("No");
		else puts("Yes");
}
int main() {
	int T; scanf("%d", &T);
	while(T--)
		reset(), Main();
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值