二叉树:小球下落

                          小球下落

【题目大意】

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

【分析】

 先将每个结点用数组保存标记,几个小球下落,就执行几次循环,每次执行,凡是到了哪个结点处就使      标记数组变化,使其下次可以指到不同的方向。

【代码实现】

代码  1:

#include<stdio.h>
#include<string.h>
const int maxd=20;
int s[1<<maxd];  // 表示2^maxd,1的二进制数向左移动maxd位,即在1的二进制后面加了maxd个0
int main()
{
    int D,I;
    while(~scanf("%d %d",&D,&I))    // 输入叶子所在的深度D,和有多少个小球下落
    {
        memset(s,0,sizeof(s));
        int k,n=(1<<D)-1;       // n为最大结点编号
        for(int i=0;i<I;i++)
        {
            k=1;        // 从堆顶开始
            for( ; ; )
            {
                s[k]=!s[k];    // 经过后改变活塞方向
                k=s[k]? k*2:k*2+1;  // 判断往哪方向走
                if(k>n)         // 越界跳出
                    break;
            }
        }
        printf("%d\n",k/2);
    }
    return 0;
}

这个代码简单但数据太大就会超时,很适合了解小球下落的过程

代码  2:

#include<stdio.h>
#include<string.h>
int main()
{
    int D,I;
    while(~scanf("%d %d",&D,&I))
    {
        int k=1;
        for(int i=0;i<D-1;i++)  // 有D层,就遍历D次
            if(I%2)         // I个小球到每一层时,只考虑第I个就行了,如果它为奇数它就往左走,如果它为偶数他就往右走
        {
            k=k*2;
            I=(I+1)/2;
        }
        else
        {
            k=k*2+1;
            I/=2;
        }
        printf("%d\n",k);
    }
    return 0;
}
/*
输入:
4 2
3 4
10 1
2 2
8 128
16 12345
输出:
12
7
512
3
255
36358
*/

时间: 2024-11-07 09:34:08

二叉树:小球下落的相关文章

二叉树 小球下落问题

#include <stdio.h> #include <string.h> #define MAXD 20 int state[1<<MAXD]; int main() { int D, I; while(scanf("%d%d", &D, &I) == 2) { int i, k, n = (1<<D)-1; memset(state, 0, sizeof(state)); for(i = 0; i < I; i

UVa679 小球下落(树)

UVa679 小球下落(树) 题目大意 小球从一棵所有叶子深度相同的二叉树的顶点开始向下落,树开始所有节点都为0.若小球落到节点为0的则往左落,否则向右落.并且小球会改变它经过的节点,0变1,1变0.给定树的深度D和球的个数I,问第I个小球会最终落到哪个叶子节点. 题意容易理解,紫书上给了一个模拟的做法,但这样会超时.后面的想法我觉得很巧妙. 每个小球都会落入根节点,第一个小球一定是向左,第二个向右,所以只看小球编号的奇偶性就可以知道它最终是落在哪一棵子树中.对于进入左子树的小球,通过判断其奇偶

算法练习--小球下落

小球下落: 完全二叉树,最大深度D.所有节点从上到下从左到右编号为1,2,3...2的D次方-1.在节点1处放一个小球,它会往下落.每个内节点上都由一个开关,初始全部关闭,当每次有小球落到一个开关上时,它的状态都会改变.当小球达到一个内节点时,如果该节点上的开关关闭,往左走,否则往右走,直到遍历到叶子节点.问题,输入 深度和小球个数输出节点编号 输入 4 2  输出 12输入 3 4  输出 7 参考实现 function f(depth,count){ var states = new Arr

UVa 679小球下落(二叉树的编号)

题意:二叉树按层次遍历从1开始标号,所有叶子结点深度相同,每个结点开关初始状态皆为关闭,小球从根结点开始下落(小球落在结点开关上会使结点开关状态改变),若结点开关关闭,则小球往左走,否则往右走,给定二叉树深度D,求第I个小球所落到的叶子结点编号. 分析:对于每一个结点,若小球当前编号为k, k为奇数,则这个小球是第(k+1)/2个落在此处的,则往左走; k为偶数,则这个小球是第k/2个落在此处的,则往右走; 从根结点到叶子结点需判断D-1次. 比如,假如I为15,则这是第15个落在根结点的小球,

【UVa-679】小球下落——二叉树的编号

在结点1处放一个小球,它会往下落.每个内结点上都会有一个开关,初始全部关闭,当每次有小球落到一个开关上时,状态都会改变.当小球到达一个结点是,如果结点上的开关关闭,则往左走,否则往右走,直到走到叶子的结点,如图. Sample Input 5 4 2 3 4 10 1 2 2 8 128 -1 Sample Output 12 7 512 3 255 [分析] 对于一个结点K,其左结点和右结点分别为2k和2k+1. 小球落到结点处,先改变,后选择. [代码] 1 #include<cstdio>

Uva 679(Dropping Balls)小球下落

题目描述有一棵二叉树,最大深度为D,且所有叶子的深度都相同.所有结点从上到下从左到右编号为1,2,3,…,2D-1.在结点1处放一个小球,它会往下落.每个内结点上都有一个开关,初始全部关闭,当每次有小球落到一个开关上时,它的状态都会改变.当小球到达一个内结点时,如果该结点上的开关关闭,则往左走,否则往右走,直到走到叶子结点,如图所示. 一些小球从结点1处依次开始下落,最后一个小球将会落到哪里呢?输入叶子深度D和小球个数I,输出第I个小球最后所在的叶子编号.假设I不超过整棵树的叶子个数.D≤20.

小球下落

小球从n米高处自由下落,每次弹起的高度是下落高度的70%,当小球弹起的高度不足原高度的千分之一时,小球很快会停止跳动,请计算小球在整个弹跳过程中所经历的总路程(忽略弹起高度不足原高度千分之一的部分).(注:本题计算过程请用双精度实数) 1 #include<iostream> 2 #include<iomanip> 3 using namespace std; 4 int main() 5 { 6 double H; 7 cin>>H; 8 double h0=H*0.

Dropping Balls(小球下落)

紫书P148,例题6-6 Sample Input 4 2 3 4 10 1 2 2 8 128 Sample Output 12 7 512 3 255 这应该不仅仅是一棵完全二叉树,题目中说保证所有叶子节点的深度都相同,所以这是一颗满二叉树. 这里要弄清满二叉树的一些概念和性质,首先,对于一颗满二叉树来说,他每一层的节点数都达到最大,那么对于一个K层的满二叉树来说,他的节点数有(2^k)-1个 而且研究满二叉树和完全二叉树的一个好处在于他可以实现顺序存储,如图中的可以表示为 值   :1 2

6_6 小球下落(UVa679)&lt;完全二叉树编号&gt;

有K个球从一完整二叉树(fully binary tree,FBT)的树根(root)一个一个往下掉.当这个球遇到非终端节点时,可能往左子树跑,也可能往右子树跑,如此直到这颗球到达终端节点(也就是树叶)为止.至于在非终端节点时球该往左或往右的决定乃是由2个值true,false来控制的.如果这非终端节点的现在的值为false,则球来的时候会往左子树走,但是这个值会变为true.如果这非终端节点的现在的值为true,则球来的时候会往右子树走,但是这个值会变为false.请注意:一开始时所有非终端节