洛谷P3952 时间复杂度题解

17年提高组的原题,相当有练习的价值。题目来直接切切入正题。这个题就是个大模拟,难于处理的原因在于需要注意的细节比较多。只要挑选好模拟的数据结构,处理好细节问题,这道题就可以A掉了。大致设想为了模拟循环的嵌套关系,数据结构上选择先进后出的栈结构。 考虑到在计算嵌套层数同时还需要判定循环变量是否重复。所以,需要同时维护两个栈,一个统计层数,一个统计变量。(有一个需要注意的点,就是在读入的...
摘要由CSDN通过智能技术生成

17年提高组的原题,相当有练习的价值。
题目

来直接切切入正题。

这个题就是个大模拟,难于处理的原因在于需要注意的细节比较多。只要挑选好模拟的数据结构,处理好细节问题,这道题就可以A掉了。

大致设想

为了模拟循环的嵌套关系,数据结构上选择先进后出的栈结构。 考虑到在计算嵌套层数同时还需要判定循环变量是否重复。所以,需要同时维护两个栈,一个统计层数,一个统计变量。

(有一个需要注意的点,就是在读入的时候,最好不要使用字符,而是用字符串,可以避免一系列的扯皮问题。)

开始模拟

  • 每组数据,读入行数和复杂度字符串,从字符串中提取指定复杂度。(注意,复杂度的提取有两种情况,不是O(1)时还需要注意指定复杂度可能是多位数)
    • 每一行数据,先读第一个字符,
      是E则
      弹栈并继续 ,若栈已经清空不能弹栈,说明出现了额外结束的情况,应标记错误。 (注意弹栈不要让栈顶为负RE警告)
      是F则:
      • 继续读入循环变量并判定重复并记录,重复则标记错误

      • 读入循环始末,判断并计算该层的复杂度贡献。共可能有四种情况:

        • 前数后数,判断大小,前小后大,常数;前大后小,无效。
        • 前n后n,常数
        • 前数后n,一个标准的循环,复杂度指数指数加一。
        • 前n后数,n很大,所以无效。

        在计算这里的复杂度时,应该由上一层继承而来。

        • 复杂度常数时,指数不变,照抄上一位
        • 复杂度n时,指数加一,抄上一位并加一。
        • 无效复杂度时,定为负无穷,令后面的循环一并无效。

        (需要注意的是:由于栈顶从0开始计数,照抄上一位时需要判定是否为第一位,当然,从1开始计数可以避免这个问题。)

      • 统计答案,令当前最高统计复杂度与改位复杂度取大

      • 栈顶向前移动。

易错点总结

WA血泪史,划重点!!!

1 输入使用字符串代替字符.
2. 弹栈时注意栈顶不要减为负数
3. 数字可能不止一位
4. 记栈时注意首元素没有前一位

代码

C:

#include<stdio.h>
#include<string.h>
#define N 200
#define INF 1 << 30

int stack[N];		//统计层数 
char cstack[N];		//统计变量 
char ch[20],ch2[20];

//检查数组中是否包含元素k 
bool check(char ch[],int len,char k)
{
   
	for(int i = 0;i < len;i++)
	{
   
		if(ch[i] == k)
		{
   
			return true;
		}
	}
	return false;
}

//字符串转数字 
int getNumber(char ch[])
{
   
	int num = 0;
	for(int i = 0;i < strlen(ch);i++)
	{
   
		num = num * 10 + ch[i] - '0';
	}
	return num;
}

int max(int a,int b)
{
   
	return a > b ? a : b;
}

int main()
{
   
	int T;		//组数 
	int num;	//给定复杂度 
	int ma;		//统计复杂度 
	int n;		//每组行数 
	int top;	//栈顶 
	char a,b;	//循环始末 
	bool flag;	//错误标记 
	
	//读入组数 
	scanf("%d",&T);
	
	while(<
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值