Problem D: 小球下落
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 66 Solved: 42
[ Submit][ Status][ Web Board]
Description
有一颗二叉树,最大深度为D,且所有叶子的深度都相同。,所有叶子从上到下从左到右编号为1,2,3,...,,2^D-1。在结点1处放一个球,它会往下落。每个内结点上都有一个开关,初始全部关闭,当每次有小球落到一个开关上时,它的状态都会改变。当小球到达一个内结点时,如果该结点上的开关关闭,则往左走,否则往右走,直到走到叶子结点,如图:
一些小球从结点1处依次开始下落,最后一个小球将会落到哪里?
Input
输入有多组,每组包含两个整数,叶子深度D和小球个数I,I不超过整棵树的叶子个数,D<=20。
Output
输出第I个小球最后所在的叶子编号。
Sample Input
3 3 3 4
Sample Output
5 7
HINT
解题思路:
I个小球依次从顶点开始下落,每到达一个节点,该节点的开关状态发生改变。当开关闭合时,小球向左走,反之向右走。D层数需要2^D-1个节点来构成完全二叉树
然后对每一个小球下落的过程进行模拟,这里我们可以用一个数组来表示开关的状态,初始状态开关均关闭,因此数组全部置为0,第一个小球从顶点开始下落,此时顶点的开关打开,小球向左走,小球的编号*2,若向右走,小球编号*2+1,继续这样向下走,当小球的编号大于最大编号时,说明,小球出界,结束循环,进行下一个小球的模拟,当最后一个小球出界时,结束循环,输出最后一个小球出界前的编号。
代码实现:
#include<iostream>
#include<string.h>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAX=1048576;
int a[MAX];
int main()
{
int D,I,flag;
while(cin>>D>>I)
{
memset(a,0,sizeof(a));
int max=pow(2,D)-1;
for(int i=0;i<I;i++)
{
flag=1;
while(1)
{
a[flag]=!a[flag];
flag=a[flag]?flag*2:flag*2+1;
if(flag>max)
break;
}
}
cout<<flag/2<<endl;
}
}