• 信息学奥赛一本通 1363:小球(drop)


    【题目链接】

    ybt 1363:小球(drop)

    【题目考点】

    1. 二叉树

    【解题思路】

    该树是满二叉树,深度D最大为20
    第1层有1个结点,第2层有2个结点,…,第D层有 2 D − 1 2^{D-1} 2D1个结点,总结点数量为 1 + 2 + . . . + 2 D − 1 = 2 D − 1 1+2+...+2^{D-1}=2^D-1 1+2+...+2D1=2D1,D最大为20,那么整棵树最大结点数量为 2 20 − 1 = 1048575 2^{20}-1=1048575 2201=1048575

    解法1:链式存储结构二叉树

    结点池大小设为1100000,大于最大结点数量。
    每个结点中保存一个布尔值。
    循环I次,模拟题目描述的过程,小球到一个结点时,如果该结点值为真,该值变为假,走右子树。如果该结点值为假,该值变为真,走左子树。
    记录小球最后落在的叶子结点时的位置。

    解法2:顺序存储结构二叉树

    设bool类型数组tree,大小设为1100000,初值为false。tree[i]表示第i个结点的值。
    第i结点的左孩子编号为2*i,右孩子编号为2*i+1,双亲结点编号为i/2(整除运算)。
    总结点数量为 2 D − 1 2^D-1 2D1,先求出该值记为mx。那么最后一个分支结点为最后一个结点即第mx结点的双亲,为mx/2。
    而后循环I次,p表示当前小球所在的结点编号。如果该结点值为真,该值变为假,走右子树。如果该结点值为假,该值变为真,走左子树。
    最后p的位置即为小球落在的叶子结点的位置。

    【题解代码】

    解法1:链式存储结构二叉树

    #include 
    using namespace std;
    #define N 1100000
    struct Node
    {
        int n, left, right;//n:编号 left, right:左后孩子的地址
    	bool v;//布尔值 
    };
    Node node[N];//结点池 
    int p, D, I, ans;
    int create(int num, int d)//生成值为num的结点的树,根的层次为d 
    {
        if(d > D)
            return 0;
        int np = ++p; 
        node[np].n = num;
        node[np].left = create(2*num, d+1);
        node[np].right = create(2*num+1, d+1);
        return np;
    }
    void fall(int r)
    {
        if(node[r].left == 0 && node[r].right == 0)//如果r是叶子结点 
        {
            ans = node[r].n;//记录最后一次小球落在的叶子结点编号 
            return;
        }
        if(node[r].v)//如果值为真 
        {
            node[r].v = false;//变为假 
            fall(node[r].right);//走右子树 
        }
        else//如果值为假 
        {
            node[r].v = true;//变为真 
            fall(node[r].left);//走左子树 
        }
    }
    int main()
    {   
        cin >> D >> I;
        create(1, 1);
        for(int i = 1; i <= I; ++i)
            fall(1);
        cout << ans;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    解法2:顺序存储结构二叉树

    #include 
    using namespace std;
    bool tree[1100000];//顺序存储结构二叉树 初始值为false
    int main()
    {
        int mx, D, I, p;//p为此时指向的结点在数组中的下标 第1位置是树的根
        cin >> D >> I;
        mx = int(pow(2, D))-1;
    	for(int i = 1; i <= I; ++i)
        {
            p = 1;
            while(p <= mx/2)//叶子结点那一层不用计算
            {
                if(tree[p])
                {
                    tree[p] = false;
                    p = 2 * p + 1;//走右子树
                }
                else
                {
                    tree[p] = true;
                    p = 2 * p;//走左子树
                }
            }
        }
        cout << p;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
  • 相关阅读:
    现货白银交易时间笔记
    前端食堂技术周刊第 98 期:Bun 1.0、Turbo 放弃 TS、Biome 另起炉灶、Bundler 的设计取舍、Node 最佳实践
    Fast-MVSNet CVPR-2020 学习笔记总结 译文 深度学习三维重建
    5个基于.Net Core值得推荐的CMS开源项目
    java计算机毕业设计ssm+vue微空间私人定向共享系统
    Diffusion Model论文/DALL E 2
    puppeteer实现网页截图
    2.4 Go语言中的数组(Array)
    opencv视频文件的读取,处理与保存
    学成在线第六天
  • 原文地址:https://blog.csdn.net/lq1990717/article/details/126309056