例题6-6 UVA679 Dropping Balls(23行AC代码)

紫书刷题进行中,题解系列【GitHub|CSDN

例题6-6 UVA679 Dropping Balls(23行AC代码)

题目大意

现有一个D层高的满二叉树,小球从根开始向下滚落,直至叶子结点,每个结点有开关标志flag(初值为false),滚落时左右子树选择规则如下

  • flag=false:flag置为true,向左子树滚落
  • flag=true:flag置为false,向右子树滚落

现求第I个小球落在那个叶子结点

思路分析

直接用静态数组依次模拟I个小球滚落,会超时。因此需要找规律来优化时间,有以下结论:

假设第i个小球Qi是第j个经过结点Vn,可根据j来判断小球下一个走向,若j为偶数,走右子树;否则,走左子树

假设当前结点为根节点,即V1,那么第1个小球走左子树,第二个走右子树,以此类推

假设当前结点为V2,第1,2,3个经过V2的小球为Q1,Q3,Q5,抽象成公式即j=(i+1)/2

假设当前结点为V3,第1,2个经过V2的小球为Q2,Q4,抽象为公式:j=i/2

通过这种方式,可以仅根据I的奇偶性依次判断,时间复杂度为O(logn),并且节省空间

AC代码(C++11,完全二叉树,规律优化)

#include<bits/stdc++.h>
using namespace std;
int T, D, I;
int main() {
    scanf("%d", &T);
    while (T --) {
        scanf("%d %d", &D, &I);
        long long ans=1;
        for (int i = 1; i <= D-1; i ++) { // 模拟I个小球掉落
            if (I % 2 == 1) { // I表示第几个经过当前点
                I = (I+1)/2; // 更新
                ans *= 2;
            }
            else { // 偶数走右子树
                I /= 2;
                ans = ans*2 + 1;
            }
        }
        printf("%lld\n", ans);
    }
    scanf("%d", &T); // 最后的-1,多余的输入!
    return 0;
}
发布了128 篇原创文章 · 获赞 87 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_40738840/article/details/104285935