zoukankan      html  css  js  c++  java
  • 小球下落 (二叉树的应用)

    小球下落 (二叉树的应用)


    有一棵二叉树,最大深度为D,且所有叶子的深度都相同。所有结点从上到下从左到右编号为1,2,3,...,2^D-1。在结点1处放一个小球,它会往下落。每个内结点上都有一个开关,初始全部关闭,当每次有小球落到一个开关上时,它的状态都会改变。当小球到达一个内结点时,如果该结点上的开关关闭,则往左走,否者往右走,直到走到叶子结点。
    一些小球从结点1处依次开始下落,最后一个小球将会落到哪里呢?输入叶子深度D和小球个数I,输出第I个小球最后所在的叶子编号。假设I不超过整棵树的叶子个数(即2^(D-1))。D<=20。输入最多包含1000组数据。
    样例输入:
    4 2
    3 4
    10 1
    2 2
    8 128
    16 12345
    样例输出:
    12
    7
    512
    3
    255
    36358

    [分析]
    不难发现,对于一个结点k,它的左儿子、右儿子的编号分别是2k和2k+1 。所以方法[1] 可以模拟程序输出结果。但是这种方法的缺点是:运算量太大 ,由于小球个数I可以高达2^(D-1),每个测试数据下落总层数可能会高达2^19*(20-1)=9961472。所以效率比较低。

    考虑方法[2] ,每个小球都会落在根结点上,因此前两个小球必然是一个在左子树,一个在右子树。一般地,只需看小球的编号的奇偶性,就能知道它是最终在哪棵子树中 。对于那些落入根结点左子树的小球来说,只需知道该小球是第几个落在根的左子树里的,就可以知道它下一步往左还是往右了。以此类推,直到小球落到叶子上。当I是奇数时,它是往左走的第(I+1)/2个小球;当I是偶数时,它是往右走的第I/2个小球。这样,可以直接模拟最后一个小球的路线 。这样,程序的运算量就与小球编号无关 了,而且节省了一个巨大的数组 tree,程序的效率很高。

    [1] 通过模拟程序输出结果。

    [cpp] view plain copy

    1. #include <cstdio>  
    2. #include <string>  
    3. #include <ctime>  
    4. #include <cstdlib>  
    5. using std::string;  
    6. const int manx=20;  
    7. int tree[1<<manx];// the biggest number of node is 2^manx -1  
    8. int main()  
    9. {  
    10. 10.     int D;// depth of tree, less_equal than 20  
    11. 11.     int I;// number of small ball  
    12. 12.     clock_t beg, end;  
    13. 13.     while (scanf("%d%d",&D,&I)==2)  
    14. 14.     {  
    15. 15.         beg=clock();  
    16. 16.         memset(tree,0,sizeof(tree));  
    17. 17.         int k, n=(1<<D)-1;// n is the biggest number of nodes  
    18. 18.         for (int i=0; i<I; ++i)  
    19. 19.         {  
    20. 20.             k=1;  
    21. 21.             for (;;)  
    22. 22.             {  
    23. 23.                 tree[k]=!tree[k];  
    24. 24.                 k=tree[k] ? k*2 : k*2+1;// choose the direction by switch tree[k]  
    25. 25.                   
    26. 26.                 if (k>n)// out of range     
    27. 27.                     break;  
    28. 28.             }  
    29. 29.         }  
    30. 30.         end=clock();  
    31. 31.         printf("%d/n",k/2);// the number of node before out of range  
    32. 32.         printf("time used: %lfs/n",(double)(end-beg)/CLOCKS_PER_SEC);  
    33. 33.     }  
    34. 34.     return 0;  

    35. }  

    36. /* 

    37. 16 65535 

    38. 49151 

    39. time used: 0.016000s 

    40. */  

    [2]  根据规律输出结果。

    [cpp] view plain copy

    1. #include <cstdio>  
    2. #include <string>  
    3. #include <ctime>  
    4. #include <cstdlib>  
    5. using std::string;  
    6. int main()  
    7. {  
    8.     int D;// depth of tree, less_equal than 20  
    9.     int I;// number of small ball  
    10. 10.     clock_t beg, end;  
    11. 11.     while (scanf("%d%d",&D,&I)==2)  
    12. 12.     {  
    13. 13.         beg=clock();  
    14. 14.         int k=1;  
    15. 15.         for (int i=0; i<D-1; ++i)  
    16. 16.         {             
    17. 17.             if (I%2)  
    18. 18.             {  
    19. 19.                 // odd  
    20. 20.                 k=k*2;   
    21. 21.                 I=(I+1)/2;  
    22. 22.             }  
    23. 23.             else  
    24. 24.             {  
    25. 25.                 //even  
    26. 26.                 k=k*2+1;  
    27. 27.                 I/=2;  
    28. 28.             }  
    29. 29.         }  
    30. 30.         end=clock();  
    31. 31.         printf("%d/n",k);  
    32. 32.         printf("time used: %lfs/n",(double)(end-beg)/CLOCKS_PER_SEC);  
    33. 33.     }  
    34. 34.     return 0;  

    35. }  

    36. /* 

    37. 16 65535 

    38. 49151 

    39. time used: 0.000000s 

    40. */  

  • 相关阅读:
    Attributes in C#
    asp.net C# 时间格式大全
    UVA 10518 How Many Calls?
    UVA 10303 How Many Trees?
    UVA 991 Safe Salutations
    UVA 10862 Connect the Cable Wires
    UVA 10417 Gift Exchanging
    UVA 10229 Modular Fibonacci
    UVA 10079 Pizza Cutting
    UVA 10334 Ray Through Glasses
  • 原文地址:https://www.cnblogs.com/Renyi-Fan/p/7741087.html
Copyright © 2011-2022 走看看