679 - Dropping Balls

Dropping Balls

PS:因为该题排版较麻烦,这里给出OJ网址:UVa679 - Dropping Balls


有一棵二叉树,最大深度为D,且所有叶子的深度都相同。所有结点从上到下从左到右编号为1, 2, 3,…, 2D-1。在结点1处放一个小球,它会往下落。每个内结点上都有一个开关,初始全部关闭,当每次有小球落到一个开关上时,状态都会改变。当小球到达一个内结点时,如果该结点上的开关关闭,则往左走,否则往右走,直到走到叶子结点,如图6-2所示。

这里写图片描述

一些小球从结点1处依次开始下落,最后一个小球将会落到哪里呢?输入叶子深度D和小球个数I,输出第I个小球最后所在的叶子编号。假设I不超过整棵树的叶子个数。D≤20。输入最多包含1000组数据。

样例输入:

4 2
3 4
10 1
2 2
8 128
16 12345

样例输出:

12
7
512
3
255
36358

#include <cstdio>
// 该方法会超时
// #include <cstring>
// using namespace std;
//const int maxDepth = 20;

//int tree[1 << maxDepth];
//
//int main() {
//    // l组数据
//    int l;
//    // D层满二叉树,I个小球
//    int D,I;
//    scanf("%d", &l);
//    while(l--) {
//        scanf("%d%d", &D, &I);
//        memset(tree, 0, sizeof(tree));
//        // 最大结点编号
//        int n = (1 << D) - 1;
//        int k;
//        for(int i = 0; i < I; i++) {
//            // 结点当前位置
//            k = 1;
//            while(true) {
//                // 置反
//                tree[k] = !tree[k];
//                // false->true,走左子树
//                // true->false,走右子树
//                if(tree[k]) {
//                    k = k * 2;
//                } else {
//                    k = k * 2 + 1;
//                }
//
//                if(k > n) {
//                    break;
//                }
//            }
//        }
//        // 最后一次的叶子节点编号
//        printf("%d\n", k / 2);
//    }
//    return 0;
//}

int main() {
    // l组数据
    int l;
    // D层满二叉树,I个小球
    int D,I;
    scanf("%d", &l);
    while(l--) {
        scanf("%d%d", &D, &I);
        int k = 1;
        // 模拟路径
        for(int i = 0; i < D - 1; i++) {
            // 如果I为奇数,则向左子树移动
            // I为偶数,则向右子树移动
            if(I % 2) {
                k *= 2;
                I = (I + 1) / 2;
            } else {
                k = k * 2 + 1;
                I /= 2;
            }
        }
        printf("%d\n", k);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值