完全二叉树
有一颗二叉树,最大深度为D,且所有叶子的深度都相同。所有结点从左到右从上到下的编号为1,2,3,·····,2的D次方减1。在结点1处放一个小猴 子,它会往下跑。每个内结点上都有一个开关,初始全部关闭,当每次有小猴子跑到一个开关上时,它的状态都会改变,当到达一个内结点时,如果开关关闭,小猴 子往左走,否则往右走,直到走到叶子结点。一些小猴子从结点1处开始往下跑,最后一个小猴儿会跑到哪里呢?
输入
输入二叉树叶子的深度D,和小猴子数目I,假设I不超过整棵树的叶子个数,D<=20.最终以 0 0 结尾
输出
输出第I个小猴子所在的叶子编号
样例输入
4 2
3 4
0 0
样例输出
12
7
思路:
完全二叉树的简单应用。
性质:若完全二叉树有n个结点,则对任意结点i(1 <= i <= n),有
1.若i = 1,结点i是二叉树的根,无双亲;若i > 1,则双亲为i / 2。
2.若2i <= n,则i的做孩子是2i,若2i > n,则i无左孩子。
3.若2i + 1 <= n,则i的右孩子是2i + 1,若2i + 1 > n,则i无右孩子。
1 #include<iostream> 2 #include<string> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<algorithm> 7 using namespace std; 8 int visit[1000010]; 9 10 #define init(arr, value) memset(arr, value, sizeof(arr)) 11 #define max(a, b) return a > b ? a : b 12 13 int main() 14 { 15 int deep, node, num, i, k; //deep为二叉树的深度 16 while(scanf("%d%d", &deep, &num) && deep && num) 17 { 18 init(visit, 0); 19 node = (1 << deep) - 1; //结点个数 20 for(int i = 1; i <= num; ++i) 21 { 22 k = 1; 23 while(true) 24 { 25 visit[k] = !visit[k]; 26 if(visit[k]) k = k * 2; //左孩子 27 else k = k * 2 + 1; //右孩子 28 if(k > node) 29 break; 30 } 31 } 32 printf("%d\n", k / 2); //k为叶子结点的左孩子,所以除2 33 } 34 return 0; 35 }