POJ 1105 S-Trees(二分)

POJ 1105 S-Trees

题意: 定义一种结构叫做S-tree,给定深度n,S-tree是一颗深度为n(n<=7)的满二叉树(根节点深度为0),树节点上标记着变量的名字,并且树的同一层上的变量名相同,叶子节点为1,或者0。例如给定深度为3的两颗树
在这里插入图片描述
所以表达一棵树只需要给出变量序列和叶子节点即可,左边的树可以表达为

x1 x2 x3 00000111

右边的树表达为:

x3 x1 x2 00010011

x1, x2, x3通过VVA(Variable Values Assignment)赋值, 例如VVA=110对于第一个图表示x1 = 1, x2 =1, x3 = 1,对于第二个图表示x3 = 1, x1 = 1, x2 = 0。

给定S-tree和VVA,定义一种遍历树的方法,对于树中的节点变量,如果变量为0,则走左子树,变量为1则走右子树,那么对于VVA=110,左边的树遍历到从左往右倒数第二个叶子节点。

题目给定多个S-tree,和VVA,问遍历结果

思路: 可以按照树的遍历去做,这样思路直接。但是可以看到最后遍历树只需要知道走到哪一个叶子节点即可。

二分思路来源在于:走左子树,则最终结果一定不在叶子节点的右半侧,走右子树,最终结果一定不在叶子节点的左半侧,如此设定start,end指定搜索下标的范围,不断缩小范围,同时需要配上手工先行验证想法。

深度为n的树,叶子节点有 2 n 2^n 2n个,用数组char terminal_node[150]存储,只需要找到遍历最后的下标index即可。设叶子节点数组下标从1开始存放数字,且start=1,end= 2 n 2^n 2n,mid=(start+end)/2。对于给定的VVA,遍历前n-1个VVA的值,如果某个变量为0,走左子树,那么最终的值不可能在mid右边,那么修改end=mid,mid=(start+end)/2,如果变量为1同理,不可能在mid左边,修改start=mid,mid=(start+end)/2,按照这个步骤最终遍历完n-1个VVA,如果第n个VVA的值为0,则index = mid即为最终结果在叶子节点的下标,如果VVA=1,则index = mid+1,最后结果为terminal_node[index]

代码

#include <iostream>
#include <string>
#include <cstdio>
using namespace std;
//Accepted

int pow(int x, int y) {
    int result = 1;
    for (int i = 0; i < y; i++)
        result *= x;
    return result;
}

int s_tree_function(char vva[], int n) {
    int start = 1, end = (int)pow(2, n);
    int mid = (start + end) / 2;
    for (int i = 0; i < n - 1; i++) {
        if (vva[i] == '0') {
            end = mid;
            mid = (start + mid) / 2;
        }
        else {
            start = end;
            mid = (end + mid) / 2;
        }
    }
    if (vva[n - 1] == '1') mid++;
    return mid;
}

int main() {
    int N;
    int cases = 0;
    while (cin >> N && N != 0) {
        cases++;
        string tmp;
        for (int i = 0; i < N; i++) {
            cin >> tmp;
        }
        char terminal_node[150];
        cin.ignore(1);
        for (int i = 1; i <= (int)pow(2, N); i++) {
            terminal_node[i] = getchar();
        }

        int M; cin >> M;
        printf("S-Tree #%d:\n", cases);
        for (int i = 0; i < M; i++) {
            cin.ignore(1);
            char vva[10];
            for (int i = 0; i < N; i++) {
                vva[i] = getchar();
            }
            int index = s_tree_function(vva, N);
            cout << terminal_node[index];
        }
        cout << endl << endl;

    }

    return 0;
}

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ZJU_Main 主页 下一页 ZJU 题型分类 文演整理版 2008-3-23 数论: 1007 Numerical Summation of a Series 简单题,还是蛮有意思的 1045 HangOver 简单题 1049 I Think I Need a Houseboat 简单题 1028 Flip and Shift 简单题,可以DP/BFS/……,但是实际上有数学方法可直接判断出来 1026 Modular multiplication of polynomials 简单题,有比较简单的好算法 1307 Packets 简单题,不过也蛮经典的…… 1312 Prime Cuts 简单题 1334 Basically Speaking 简单题 1337 Pi 简单题 1342 Word Index 简单题 1349 Four Quarters 简单题 1350 The Drunk Jailer 简单题 1352 Number Base Conversion 简单题 1353 Unimodal Palindromic Decompositions 规模不大,所以是简单题…… 1354 Extended Lights Out 简单题 1362 Game Prediction 简单题 1365 Mileage Bank 简单题 1382 A Simple Task 简单题 1383 Binary Numbers 简单题 1403 Safecracker 简单题 1408 The Fun Number System 简单题 1486 Color the Tree 简单题 1487 Playing Cards 简单题 1489 2^x mod n = 1 简单题,应该有好算法,不过枚举就可以过…… 1503 One Person "The Price is Right" 简单题,POI Eggs的翻版 1512 Water Treatment Plants 简单题,组合计数 1526 Big Number 简单题,不过O(1)和O(n)还是有区别的:) 1529 Enigmatic Travel 简单题,不过个人感觉题目描述很令人费解 1530 Find The Multiple 简单题 1537 Playing with a Calculator 简单题 1577 GCD & LCM 简单题,分区联赛的题…… 1005 Jugs 简单题 1543 Stripies 简单题 1569 Partial Sums 简单题 1062 Trees Made to Order 简单题 1070 Bode Plot 简单题 1073 Round and Round We Go 简单题,142857,我喜欢^_^ 1078 Palindrom Numbers 简单题 1086 Octal Fractions 简单题 1199 Point of Intersection 简单题 1104 Leaps Tall Buildings 简单题 1110

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值