有一颗二叉树,最大深度为D,所有叶子的深度都相同。所有结点从上到下从左到右的编号分别依次是1,2,3,4,~,(2的D次方-1)。在节点1放下一个小球,它会往下落。每个内结点都有一个状态(开或关),初始时,每个内结点都处于关闭状态,当小球经过一个内结点时,开关状态会改变。当为开状态时,小球向左落下;当为关状态时,小球向下落下,直到走到叶子结点。
输出树的深度D,和小球数量I
输出第I个小球落到的结点编号
输入样例:
4 2
3 4
2 2
16 12345
输出样例:
12
7
3
36358
模拟小球的下落
#include <iostream>
#include <cstring>
using namespace std;
const int MAX_N=20;
int sw[1<<MAX_N]; //每个节点的开关
int main()
{
int d,i,k;
while(cin >> d >> i)
{
memset(sw,0,sizeof(sw));
int MAX_K = 1 << (d-1) ;
for(int j=0; j < i; j++)
{
k=1;
while(1)
{
sw[k]=!sw[k];
k = sw[k] ? k*2 : k*2+1;
if(k>=MAX_K) break ;
}
}
cout << k << endl;
}
return 0;
}
当题目的i为奇数时最后一个球经过第1个结点往左走为偶数则往右走
经过结点2的球总共有(i+1)/2个如果它为奇数的话接下来会往左走偶数则往右走以此内推
经过结点3的球总共有i/2个如果它为奇数的话接下来会往左走偶数则往右走以此内推
#include <iostream>
using namespace std;
int main()
{
int d, i;
while(cin >> d >> i)
{
int k = 1;
for(int j=0; j<d-1; j++)
{
if(i%2)
{
k = k*2;
i=(i+1)/2;
}
else
{
k=k*2+1;
i/=2;
}
}
cout << k << endl;
}
return 0;
}