POJ1472浅析------Instant Complexity

本文介绍了一种计算Pascal程序时间复杂度的方法,通过递归模拟将程序转化为数学表达式,并简化得到关于变量n的多项式。文章提供了详细的解析步骤及C语言实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大致题意:

给出一段Pascial程序,计算其时间复杂度(能计算的项则计算,不能计算则化到最简的关于n的表达式O(n),并把各项根据n的指数从高到低排列),输出时,系数为0的项不输出,系数为1的项不输出系数,指数为1的项不输出指数。

一段程序只有唯一一个BEGIN,代表程序的开始。与其对应的为最后的END,代表程序的结束。

一段程序最多只有10层循环嵌套,循环的入口为LOOP,一个LOOP对应一个END,代表该层循环的结束。

一段程序中OP的个数不限。

 

LOOP是循环的入口,其后面的数据可能是常量(非负整数),也可能是变量n,代表循环体执行的次数。

OP是语句,其后面的数据只能为常量(非负整数),代表该语句执行的次数。

 

解题思路:

此题就是一条表达式化简的模拟题,用递归直接模拟。

以第一个样例说明处理方法:

BEGIN

  LOOP n

    OP 4

    LOOP 3

      LOOP n

        OP 1

      END

      OP 2

    END

    OP 1

  END

  OP 17

END

从该例子我们可以得到一条关于n的最初表达式:

  n*(4+3*(n*1+2)+1)+17

稍微化简一下,合并同一层的OP值,得到了

n*(3*(n*1+2)+5)+17

不难看出每一个循环体都能写成k*n+i形式的子表达式,其中loop是*关系,op是+关系

 

由于最大循环次数为10,那么我们用exp[11]存储多项式的每一项的指数i和系数k=exp[i],其中exp[0]其实就是常数项,由OP语句产生

 

注意LOOP后面可能输入字符n,也可能输入数字,处理方法:用字符串输入s,若为s[0]==n,则直接作字符处理;若s[0]!=n,则认为是数字串,把它转换为int再处理。

————————————————

这道题让我纠结了好久好久,甚至钻进自己想的循环里出不来,最后还是没有解决办法。于是网上走了一下题解,发现别人写的很巧妙,借鉴了一下,部分有所改动。

参考程序地址:http://blog.youkuaiyun.com/lyy289065406/article/details/6648640

 

我的代码如下:

#include<stdio.h>
#include<string.h>     
int solve(int* exp)  
{  
    int i, x, a;
    int TempExp[11];
    char s[30];  
    scanf("%s", s);  
  
    if(s[0]=='E')      
        return 0;  
    else if(s[0]=='B')   
        while(solve(exp));     
    else if(s[0]=='O')    
    {  
        scanf("%s", s);  
        sscanf(s,"%d",&x);
        exp[0] += x; 
        return solve(exp);  
    }  
    else       
    {     
        for(i=0; i<11; i++)  TempExp[i]=0;
        scanf("%s", s);  
        while(solve(TempExp));  
  
        if(s[0]=='n')     
        {  
            for(i=10;i>0;i--)  
                TempExp[i]=TempExp[i-1];    
            TempExp[0]=0;  
        }  
        else   
        {  
            sscanf(s,"%d",&x);
            for(i=0;i<11;i++)  
                TempExp[i]*=x;  
        }  
        for(i=0;i<11;i++)  
            exp[i]+=TempExp[i];  
    }  
    return 1;  
}  
  
int main()  
{   
    char s[6];  
    int t, test, i, flag, mark; 
    int exp[11]={0};
    scanf("%d", &test);  
    for(t=1;t<=test;t++)  
    {  
        for(i=0; i<11; i++)  exp[i]=0;
        solve(exp);  
        printf("Program #%d\nRuntime = ", t);
        flag=1; mark=0;
        for(i=10; i>=0; i--)
        {   
                if(exp[i]==0)
                    continue;
                if(!flag) 
                    printf("+");
                if(exp[i]==1)
                {   mark=1;flag=0;
                    if(i==0)
                        printf("1");
                    else if(i==1)
                        printf("n");
                    else printf("n^%d", i);               
                }
                else {   mark=1;flag=0;
                         if(i==0)
                             printf("%d",exp[i]);
                         else if(i==1)
                             printf("%d*n",exp[i]);
                         else 
                             printf("%d*n^%d",exp[i], i);
                     }               
                    
        }
        if(!mark)
            printf("0");
        printf("\n\n");
    }  
    return 0;  
} 



 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值