小球下落-二叉树
来源:互联网 发布:手机号码数据库腾讯 编辑:程序博客网 时间:2024/04/29 16:23
有一颗二叉树,最大深度为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<stdio.h>#include<string.h>const int maxn=20;int s[1<<maxn]; //最大节点个数为2^maxn-1int main(){ int D,I; while(scanf("%d%d",&D,&I)==2) { memset(s,0,sizeof(s)); //开关 int k,n=(1<<D)-1; //n是最大节点编号 for(int i=0; i<I; i++) //连续让I个球下落 { k=1; for(;;) { s[k]=!s[k]; k=s[k]?k*2:k*2+1; //根据开关状态选择下落方向 if(k>n) //已经落“出界”了 break; } } printf("%d\n",k/2); //出界之前的叶子编号 } return 0;}
找规律:
当I是奇数时,它是往左走的第(I+1)/2个小球;当I是偶数时,她是往右走的第I/2个小球。这样,可以直接模拟最后一个小球的路线:
如果I是奇数,它一定会落在左子树,否则,一定是在右子树。以I为3为例,可以将它看作是从节点2开始降落的第二个球,依此类推。
#include<stdio.h>int main(){ int D,I; while(scanf("%d%d",&D,&I)==2) { int k=1; for(int i=0; i<D-1; i++) if(I%2) { k=2*k; I=(I+1)/2; } else { k=k*2+1; I/=2; } printf("%d\n",k); } return 0;}
From:《算法竞赛入门经典》
0 0
- 小球下落 二叉树
- 小球下落(二叉树)!!!!
- 小球下落-二叉树
- 二叉树:小球下落
- 二叉树:小球下落
- 小球二叉树下落
- 二叉树之小球下落
- 二叉树之小球下落
- 小球下落(二叉树)
- 小球下落(二叉树)
- UVa679 小球下落 二叉树
- 二叉树之小球下落
- 二叉树 小球下落问题
- 树和二叉树之小球下落
- 二叉树之小球下落问题
- 算法研究之二叉树小球下落
- 二叉树——小球下落问题
- 算法研究之二叉树小球下落
- 重构11-20
- 实习笔记2
- 23. 变量、作用域和内存问题
- VM虚拟机固定IP
- iTween方法详解
- 小球下落-二叉树
- 在java代码中设置TextView中DrawableLeft的方法
- 静态扫描-Godeyes for ios
- arm 编译器添加第三方库
- iOS网络监控:BMReachability
- NHibernate Delete Extension 删除扩展
- 错误与异常处理入门
- HDOJ 2037 今年暑假不AC (贪心)
- Hdu oj 2112 HDU Today