poj1472

来源:互联网 发布:多空博弈指标源码 编辑:程序博客网 时间:2024/06/07 22:07

题目较复杂。模拟+字符串处理

大致题意为:给定一个特定程序,有如下语句组成:

1)BEGIN表示开始

3)OP interger(非负)表示操作interger次

4)LOOP  n  或者是 LOOP interger(非负),表示循环n次或者interger次

5)END与LOOP和BEGIN对应分别表示循环的结束和程序的结束(类似于伪代码)

其它为空格或换行,空格或换行可以出现在任何位置,除了上述关键字和interger整数。

由题意可知:LOOP必须与END匹配,且LOOP必须在与之匹配的END之前。OP操作可以出现在BEGIN和END之间的任意位置。

分析如下:由于LOOP与最近的END匹配,而OP操作的次数是最内层循环到最外层循环次数的乘积,且BEGIN必为程序第一句,END必为程序最后一句,例如:

BEGIN

LOOP n

OP 3

LOOP 3

OP 4

END

END

END

可知OP3操作n*3次,而OP4操作n*3*4次,我们可以利用类似堆栈的结构存储各循环层次,这样在输入的同时就可以判断OP操作的镶嵌循环层次,以及每层次上的循环个数,然后计算该操作的总共的循环次数,累加到结果中即可。

这里用数组存储结果,n幂数字0——10分别初始化为0,然后在输入的同时按照上述的方法计算每个OP的循环次数,累计到相应的幂次项即可。

这里再说明一下如何动态的更新层次:每遇到LOOP就进数组(下标增大),若在与该LOOP对应的END前OP操作,则OP操作的循环镶嵌层次即为目前的最大层次,计算完循环次数后,若遇到END,则小标减一,表示循环镶嵌层次减少一个层次;若遇到LOOP则要进数组,循环镶嵌层次增加一个层次,这就是动态维护当前OP所在位置循环镶嵌层次的过程(与普通的for循环是一样的道理)。

另外就是要注意:

1)处理字符输入时,空格和行换是不同的字符,但均当作无效符号处理

2)处理OP 0操作的方法,由于OP 0表示操作次数为0次,故可以省略该操作,因为题目要求的是有效操作次数,即使循环层次再深,若为0则有效操作也为0次(很容易理解)

3)处理LOOP 0的方法,由于是循环0次,故在OP循环层次上若有LOOP为0的情况,则也可以省略该操作,原因很明显:若镶嵌层次上有一个为0,则表示该操作不能执行

另外介绍一下本题的难点:

1)如何正确累计相应幂次项?

方法:在计算每一个OP操作循环次数时,计数因子中n的个数为num,然后将数字联乘,那么该数字就因该为幂num的项(还需要累加,才能得到最后的项数)

2)  处理LOOP循环是难点。如何处理为n和为数字的两种不同情况?

方法:分别处理为n和数字的情况,其中为数字的情况比较复杂,要另外添加辅助数组记录数字的每一位,然后还原,最后由于是连续接受输入,所以需要另外的输入处理,以便下一次循环正确。

下面是代码:156K+0MS

#include<stdio.h>#include<stdlib.h>#include<string.h>#define Max 20 //最大层次为10次,取大int mi[Max]; //记录幂为i的项数struct Node{ //记录镶嵌层次上各层次的状态    bool word; //判断是否为字符nint value;//若是数字记录该数字}node[Max]; //最大镶嵌层次为10,取大char Input[Max]; //辅助数组,记录输入的整形int n; //case数目int main(){scanf("%d",&n);for(int k=1;k<=n;k++){ memset(mi,0,sizeof(mi)); //初始化为项数全0int pivot=-1; //初始化下标为-1char temp;bool right=true; // 标记是否是LOOP的对数字的特殊处理while(true){ //循环,处理输入if(right){ //若不是LOOP对数字的特殊处理temp=getchar(); //接受无效输入while(temp==' ' || temp=='\n')temp=getchar();}right=true; //若为LOOP对数字的特殊处理,则直接跳到判断类型,但是需要将值取反,因为那是上一次的输入    if(temp=='B'){ // 若为BEGIN,则再连续接受4个输入,然后循环getchar();getchar();getchar();getchar();}else if(temp=='L'){ //若为LOOP则记录循环镶嵌层次getchar(); //连续接受LOOP字符getchar();getchar();temp=getchar();while(temp==' ' || temp=='\n') // 接受无效输入temp=getchar();if(temp=='n') //若为字符n则设置标记为true,下一次输入正常处理    node[++pivot].word=true;else{ //否则处理数字输入node[++pivot].word=false; //标记为数字int index=0; //下标初始化为0Input[index++]=temp;//存储数字最高位temp=getchar();while(temp>='0' && temp<='9'){ //连续输入数字的低位部分Input[index++]=temp;temp=getchar();}right=false; //标记下一次循环直接判断即可,无需接受无效输入    while(temp==' ' || temp=='\n') //找到第一个有效字符,作为下一次的判别处理temp=getchar();int vv=1; //各位为权值1int Sum=0; //初始化为0for(int s=index-1;s>=0;s--){ // 从低位到高位转化为整数Sum+=(vv*(Input[s]-'0'));vv*=10;}node[pivot].value=Sum; //存储数字}}else if(temp=='O'){  //若为OP 操作getchar();int num=0,Sum=0,v; scanf("%d",&v); //输入数字if(v==0) //若为0,则可省略该操作continue;Sum+=v; //否则初始化为该数字bool trag=true; //标记镶嵌循环层次上是否存在循环次数为0的情况for(int i=0;i<=pivot;i++){if(!node[i].word && node[i].value==0){ //若存在为0情况trag=false;    break;}if(!node[i].word && node[i].value>0) //若为数字,则连乘Sum*=node[i].value;else if(node[i].word) //若为字符‘n'则累加,判断幂指数num++;}if(trag) // 若不再任何循环内,或者循环层次上没有次数为0的情况mi[num]+=Sum; //累加相应幂次项的项数}else if(temp=='E'){ //若为END,则要递减循环镶嵌层次getchar();getchar();if(pivot<0) //若为与开头BEGIN对应的END则要退出循环,该case结束,处理结束break;pivot--;}}printf("Program #%d\nRuntime = ",k);  //处理输出int i;bool flag=false; //标记1——10幂指数项数是否有大于0的情况,找出第一个幂次项数大于0的幂指数,第一个项不用输出'+'符号for(i=10;i>=1;i--){if(mi[i]>1){ //若存在大于1的情况flag=true;if(i>1)printf("%d*n^%d",mi[i],i); //可输出项数和幂指数elseprintf("%d*n",mi[i]); //只可输出幂指数,项数为1,不能输出break;}else if(mi[i]==1 && i==1){ //同理flag=true;printf("n");break;}else if(mi[i]==1 && i!=1){ //同理flag=true;printf("n^%d",i);break;}}if(!flag){ //若1——10都不存在项数大于0的幂指数,则检查最后的0次幂if(mi[0]>0) //若大于0,则直接输出,不用加'+'printf("%d\n\n",mi[0]);    else printf("0\n\n"); //否则为0continue;}for(int j=i-1;j>=1;j--){ //若1——10存在项数大于0的幂指数,则依次输出后续项数大于0的幂指数,注意要加’+‘if(mi[j]>1){if(j>1)printf("+%d*n^%d",mi[j],j);elseprintf("+%d*n",mi[j]);}else if(mi[j]==1 && j==1){printf("+n");}else if(mi[j]==1 && j!=1){printf("+n^%d",j);}}if(mi[0]>0) //检查0次幂,若大于0则直接输出,否则输出空行(2个)printf("+%d\n\n",mi[0]);elseprintf("\n\n");}return 0;}


 

 

 

0 0
原创粉丝点击