-
有一颗二叉树,最大深度为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为总结点数目
2*i<=n,则左孩子为2i,2*i>n,则无左孩子
2*i+1<=n,则右孩子为2i+1,否则无右孩子
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#include<math.h>
//小猴子下落
int main() {
int d,i,node,k,j,s[10010];
//输入二叉树的深度以及小猴子的数目
while(scanf("%d%d",&d,&i)==2)
{
//每次重新输入数据,得重新对s数组进行初始化为0,使用头文件string.h里面的memset函数就可以了,
memset(s,0,sizeof(s));
//node表示二叉树的总结点 2的d次方减1
node=pow(2,d)-1;
//printf("%d\n",node);
for(j=1;j<=i;j++)
{
k=1;
for(;;)
{
//描述小猴子走过之后的开关状态0-->关闭 1-->打开
s[k]=!s[k];
// printf("%d\n",s[k]);
//如果s[k]!=0即s[k]等于1,也就是走之前为0,则便是关闭,向左走
if(s[k]) k=k*2;
else k=k*2+1;
if(k>node)
break;
}
}
printf("%d\n",k/2);
}
return 0;
}
最后注意scanf的返回值表示正确输入参数的个数,等于2表示两个参数均正常输入,