UVA712 S-Tree总结

来源:互联网 发布:ubuntu 14.04 卸载 编辑:程序博客网 时间:2024/06/10 15:50

上一周的程序作业一共三道题,很快就完成了,然而上课才发现有许多好的方法都没有想到,看来自己还需要很长时间来提升自己啊。
这一次对上一周的作业进行一次总结。
第一题是UVA的712 S-Tree题目,这个我在上课便写了出来,思想很朴实。但是上课又听到了一些新的方法。
第一种方法:根据输入画出树来
按照输入顺序逐渐分析。
第一个输入一个数字n(样例是3),可以得出构建一个数组,设为ID,大小是20+21+...+2n
第二个输入是关于 xi 的输出顺序(样例给的顺序是x3,x1,x2)办法是利用字符数组对每一次输入进行存储,得出每个数的起始和终止位置,用两个数组存储。讲的有点绕,下面是对样例的操作。
  第一次:起始位置0,终止位置0   因此start[3]=0 end[3]=0
  第二次:起始位置1,终止位置2   因此start[1]=1 end[1]=2
  第m次:起始位置2m11,终止位置2m2
第三个输入是最下一层的值,可知起始位置2n11,终止位置2n2
第四个输入比较水,不提。
第五个输入是x1,x2,x3...的值。根据前面得到的start和end数组,就可以把值放在树中。
以上便把输入搞定,输出便是很简单了,直接从根节点开始,如果0,往左,如果1,往右。
AC代码

#include <iostream>#include <cstdio>#include <cstring>#include <string>const int maxn = 7;int id[1<<maxn];char terminal[1<<maxn];int start[maxn+5];int end[maxn+5];int main()//main有括号。。。 {    int C = 1;    int n;    while(scanf("%d",&n)!=EOF&&n)    {        memset(id,0,sizeof(id));        for(int i=1;i<=n;i++)        {            char variable[2];            scanf("%s",variable);            start[variable[1]-'0'] = (1<<(i-1))-1;            end[variable[1]-'0'] = (1<<i)-2;        }        scanf("%s",terminal);        int temp = (1<<n)-1;        for(int i=0;i<(1<<n);i++)        {            id[temp]=terminal[i]-'0';            temp++;        }        int m;        scanf("%d",&m);        printf("S-Tree #%d:\n",C);        C++;        int result[100];        int temp_i=0;        int temp_m = m;        while(temp_m--)        {            char value[7];            scanf("%s",value);            int len = strlen(value);            for(int i=1;i<=len;i++)            {                for(int j=start[i];j<=end[i];j++)                {                    id[j] = value[i-1]-'0';                }            }            int temp = 0;            while(temp<((1<<n)-1))//            {                if(id[temp]==0)                {                       temp = temp*2+1;                }else                {                    temp = temp*2+2;                }            }            result[temp_i] = id[temp];            temp_i++;        }           for(int i=0;i<m;i++)        {            printf("%d",result[i]);        }        printf("\n\n");    }}

一个好的方法
把样例给的x的顺序调过来。比如样例中给的011,但他是x3x1x2的顺序,所以应该是101。
调完之后,开始对给出的最后一行数组操作。开始start为0,end为2n。如果是1,则start变成中间的数。如果是0,则end变成中间的数。直到end和start相同,输出它们所在位置的值。


非常好的方法
利用2进制。比如给的101,输入顺序是x3x1x2,调整之后为110,转换成二进制,为200+211+221=6,所以输出最后一行的数中第6个数。
其实想一想,也是很好想的。
对于下方图片,第一个是x3,如果是1,那么结果就在右半段,如果是0,结果在左半段。所以是2n1x3,如此反复,最后便是上述所说的结果。
这里写图片描述
总结
1.二叉树的根节点从1开始,虽然浪费了0,但是方便程度大大提高
2.遇到0和1的题目,多想想二进制能不能搞吧
3.(1<< n-1)表示的是2n1不是2n1

原创粉丝点击