Dropping Balls, UVa679

来源:互联网 发布:周传雄 知乎 编辑:程序博客网 时间:2024/06/05 04:31

原题目链接:Dropping Balls,UVa679

A number ofKballs are dropped one by one from the root of a fully binary tree structure FBT. Eachtime the ball being dropped first visits a non-terminal node. It then keeps moving down, either followsthe path of the left subtree, or follows the path of the right subtree, until it stops at one of the leafnodes of FBT. To determine a ball’s moving direction a flag is set up in every non-terminal node withtwo values, eitherfalseortrue. Initially, all of the flags arefalse. When visiting a non-terminal nodeif the flag’s current value at this node isfalse, then the ball will first switch this flag’s value, i.e., fromthefalseto thetrue, and then follow the left subtree of this node to keep moving down. Otherwise,it will also switch this flag’s value, i.e., from thetrueto thefalse, but will follow the right subtree ofthis node to keep moving down. Furthermore, all nodes of FBT are sequentially numbered, starting at1 with nodes on depth 1, and then those on depth 2, and so on. Nodes on any depth are numberedfrom left to right.

For example, Fig. 1 represents a fully binary tree of maximum depth 4 with the node numbers 1,2, 3, ..., 15. Since all of the flags are initially set to befalse, the first ball being dropped will switchflag’s values at node 1, node 2, and node 4 before it finally stops at position 8. The second ball beingdropped will switch flag’s values at node 1, node 3, and node 6, and stop at position 12. Obviously,the third ball being dropped will switch flag’s values at node 1, node 2, and node 5 before it stops atposition 10.


Fig. 1: An example of FBT with the maximum depth 4 and sequential node numbers.

Now consider a number of test cases where two values will be given for each test. The first value isD, the maximum depth of FBT, and the second one is I, theI-th ball being dropped. You may assumethe value ofIwill not exceed the total number of leaf nodes for the given FBT.

Please write a program to determine the stop positionPfor each test case.For each test cases the range of two parametersDandIis as below:


Input

Containsl+ 2lines.

2D20,and1I524288.

Line 1lthe number of test cases
Line 2 
D1I1test case #1, two decimal numbers that are separated by one blank...
Line 
k+1DkIktest case #k
Linel+1DlIltest case #l
Linel+ 2-1a constant ‘-1’ representing the end of the input file

Output

Containsllines.

Line 1...Linek...Linel

the stop positionPfor the test case #1the stop positionPfor the test case #kthe stop position Pfor the test case #l

Sample Input

5

4 2

3 4

10 1

2 2

8 128

-1

Sample Output

12

7

512

3

255 


分析:

该题可以用数组模拟的方法来做,但是这样做的话如果二叉树的深度比较大的话,就需要一个极大的数组来保存数据。因此用数组模拟是不可取的。

每个小球都会落在根结点上,因此前两个小球必然是一个在左子树,一个在右子树。所以只需要看小球编号的奇偶性,就能知道它最终在哪棵子树中。对于那些落入根结点左子树的小球来说,只需要知道该小球是第几个落在根的左子树里的,就可以知道它下一步是往左还是往右了。依次类推,直到小球落到叶子上。

如果使用题目中给出的编号I,则当I是奇数时,它是往左走的第(I+1)/2个小球;当I是偶数时,它是往右走的第I/2个小球。这样,可以直接模拟最后一个小球的路线:

int k = 1;scanf("%d%d", &D, &I); for (int i = 0; i < D - 1; i++) {      if (I % 2) {             k = k * 2; I = (I + 1) / 2;      } else {             k = k * 2 + 1; I = I / 2;      }}printf("%d\n", k);

这样,程序的运算量就与小球编号无关了,而且节省了一个巨大的数组所占用的空间。

代码:

#include <cstdio>#include <cstring>using namespace std;int main(int argc, const char * argv[]) {    // insert code here...    //std::cout << "Hello, World!\n";    int n;    int D, I;    while (scanf("%d", &n) && n != -1) {        for (int t = 0; t < n; t++) {            int k = 1;            scanf("%d%d", &D, &I);            for (int i = 0; i < D - 1; i++) {                if (I % 2) { //当I时奇数时,它是往左走的第(I+1)/2个小球                    k = k * 2; I = (I + 1) / 2;                } else {     //当I是偶数时,它是往右走的第I/2个小球                    k = k * 2 + 1; I = I / 2;                }            }            printf("%d\n", k);        }    }    return 0;}



原创粉丝点击