UVA712 S-Tree总结

上一周的程序作业一共三道题,很快就完成了,然而上课才发现有许多好的方法都没有想到,看来自己还需要很长时间来提升自己啊。
这一次对上一周的作业进行一次总结。
第一题是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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值