大致题意:
给出一段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;
}