小球下落
有一棵二叉树,最大深度为D,且所有的叶子深度都相同。所有的结点从上到下从左到右编号为1,2,3,4…,2^D-1。在结点1处放一个小球,它会往下落。每个内结点上都有一个开关,初始全部关闭,当每次有小球落到一个开关上时,状态都会改变。当小球到达一个内结点时,如果该节点上的开关关闭,则往左走,否则往右走,直到走到叶子结点。一些小球从节点1处依次开始下落,最后一个小球将会落到哪里呢》输入叶子深度和小球个数I,输出第I个小球最后所在的叶子编号。假设I不超过整棵树的叶子个数,D<=20,输入包含1000组数据。
样例输入
4 2
3 4
10 1
2 2
8 128
16 12345
样例输出
12
7
512
3
255
36358
题记
用数组存放每个结点的开关状态模拟出每个小球的下落过程是一般思路,可以解决,但是计算量太大,如果D=20而且有1000组数据肯定要TLE了,所以我们可以只模拟最后一个小球的下降过程。小球每经过一个结点就会改变开关状态,如果当前这个小球经过这个结点(可以假设这里相当一个关卡,有个门卫把守,他会根据你是第奇数个还是偶数个来到这的小球,让你往左或者往右),如果你这个小球是第奇数个经过这里的小球,那你往左,第偶数个就往右。每一层都是这样的,这样一来一个for循环就能解决了。
代码如下
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int D,I;
while(scanf("%d %d",&D,&I)==2){
int k=1;
for(int i=0;i<D-1;i++) //一共下降D-1次,每一层都做同样的抉择,k用来记录小球当前位置的编号
if(I%2==0){ //I是偶数那么这个小球就是第(I/2)个从这个结点右边下落的小球
k=2*k+1;
I=I/2;
}
else{ //I是奇数那么这个小球就是第((I+1)/2)个从这个结点左边下落的小球
k=2*k;
I=(I+1)/2;
}
printf("%d\n",k);
}
return 0;
}