1363:小球(drop)

2023-10-17 01:50
文章标签 小球 drop 1363

本文主要是介绍1363:小球(drop),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【题目描述】
许多的小球一个一个的从一棵满二叉树上掉下来组成FBT(Full Binary Tree,满二叉树),每一时间,一个正在下降的球第一个访问的是非叶子节点。然后继续下降时,或者走右子树,或者走左子树,直到访问到叶子节点。决定球运动方向的是每个节点的布尔值。最初,所有的节点都是false,当访问到一个节点时,如果这个节点是false,则这个球把它变成true,然后从左子树走,继续它的旅程。如果节点是true,则球也会改变它为false,而接下来从右子树走。满二叉树的标记方法如下图:
在这里插入图片描述

因为所有的节点最初为false,所以第一个球将会访问节点1,节点2和节点4,转变节点的布尔值后在在节点8停止。第二个球将会访问节点1、3、6,在节点12停止。明显地,第三个球在它停止之前,会访问节点1、2、5,在节点10停止。

现在你的任务是,给定FBT的深度D,和I,表示第I个小球下落,你可以假定I不超过给定的FBT的叶子数,写一个程序求小球停止时的叶子序号。

【输入】
一行包含两个用空格隔开的整数D和I。其中2≤D≤20,1≤I≤524288。

【输出】
对应输出第I个小球下落停止时的叶子序号。

【输入样例】
4 2
【输出样例】
12

分析

  1. 可以用链式存储二叉树,也可以用数组顺序存储;然后就是模拟题上的要求,先建树,然后是I次从根节点向下走;
  2. 该树是满二叉树,深度D最大为20,第1层有1个结点,第2层有2个结点,…,第D层有2^(D-1)个结点,总结点数量为 2^D-1,所以数组开到1100000;
  3. 至于建树可以参考前几篇文章,小球最后落得位置,就是走到叶子结点的时候(node[u].left == 0 && node[u].right == 0),否则就改变当前的var状态,然后向左孩子或右孩子出发;
  4. 参考君义大佬的:信息学奥赛一本通 1363:小球(drop)

解法一:链式存储

需要注意idx并不是图上的编号,而是根据建立结点的顺序来进行编号的,所以结构体有一个id来记录和图上一样的编号;

#include <bits/stdc++.h>using namespace std;
struct Node {bool val;int id, left, right;
};
const int N = 1100000;//2^20-1
Node node[N];
int idx;//结点编号
int D, I, ans;int createTree(int u) {int res;if (u >= pow(2, D) - 1)return 0;res = ++idx;node[res].id = u;node[res].val = false;node[res].left = createTree(2 * u);node[res].right = createTree(2 * u + 1);return res;
}void solve(int u) {if (node[u].left == 0 && node[u].right == 0) {//当前是叶子结点,也就是小球落得位置ans = node[u].id;return;}if (node[u].val == false) {node[u].val = true;solve(node[u].left);} else {node[u].val = false;solve(node[u].right);}
}int main() {cin >> D >> I;createTree(1);for (int i = 0; i < I; ++i)solve(1);cout << ans;return 0;
}

解法二:顺序存储

while循环结束,说明走到了叶子结点下一个结点,并多乘了2,或又加了个1;输出应该为出界之前的叶子结点编号,因为现在的u的值是2u或2u+1,所以需要除2;

#include <bits/stdc++.h>using namespace std;const int N = 1100000;//2^20-1
bool tree[N];
int D, I, u;int main() {cin >> D >> I;for (int i = 1; i <= I; ++i) {u = 1;//每次从根节点开始走while (1) {if (u >= pow(2, D) - 1)break;if (tree[u]) {//向右走tree[u] = false;u = u * 2 + 1;} else {tree[u] = true;u = u * 2;}}}//当前结点的上一个结点,就是叶子结点cout << u / 2;return 0;
}

这篇关于1363:小球(drop)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/222132

相关文章

12个小球 梅氏砝码问题

1. 12个小球,其中有一个是坏球。有一架天平。需要你用最少的称次数来确定哪个小球是坏的并且它到底是轻还是重。 来源:http://blog.csdn.net/pongba/article/details/2544933 这个问题是一道流传已久的智力题。网络上也有很多讲解,还有泛化到N个球的情况下的严格证明。也有零星的一些地方提到从信息论的角度来看待最优解法。本来我一直认

Android 自定义View控件,实现跟随手指触摸移动的小球

Android UI组件是通过继承View类,然后绘制内容,比如ImageView,TextView等组件都是继承View类。 当Android系统提供的组件功能不能满足需求时,可以通过继承View类重写一个或多个方法,派生自定义的组件,View类常用重写方法: 1.构造器:View子类最基本的重写方法 protected voidonDraw(Canvas canvas) public

ondrag 事件_html5拖放(Drag和Drop)

二、相关重点 DataTransfer 对象:退拽对象用来传递的媒介,使用一般为Event.dataTransfer。 draggable 属性:就是标签元素要设置draggable=true,否则不会有效果,例如: <div title="拖拽我" draggable="true">列表1</div> ondragstart 事件:当拖拽元素开始被拖拽的时候触发的事件,此事件作用在被拖曳元

Hive操作——删除表(drop、truncate)

Hive操作——删除表(drop、truncate) Hive删除操作主要分为几大类:删除数据(保留表)、删除库表、删除分区。我将以下图为例清空iot_devicelocation中的数据,之后再删除表、库等。 首先来看一下iot_deivcelocation中的数据。 select * from iot_deivcelocation

Android 自定义控件 loding小球

以下为参照博客    http://blog.csdn.net/guimianhao9833/article/details/74858472  首先看下效果图: 步骤: 1.继承view,并需要三个构造函数。 public MyView(Context context) {//注意不要默认实现,记得修改。 this(context, n

面试or笔试6——小球下落距离

小东和三个朋友一起在楼上抛小球,他们站在楼房的不同层,假设小东站的楼层距离地面N米,球从他手里自由落下,每次落地后反跳回上次下落高度的一半,并以此类推知道全部落到地面不跳,求4个小球一共经过了多少米?(数字都为整数) 给定四个整数A,B,C,D,请返回所求结果。 测试样例: 100,90,80,70 返回:1020 根据极限的思想可直接求得单个小球的下落距离之和为3*N c

移动的小球

VB中有个例子为“移动的小球”,下面有两种编码。一种可以运行成功,另一种不能运行成功。 这个代码不能运行成功。 这个代码可以运行成功。 按照逻辑来来说,这两种代码,均可运行成功。但是第一种并不是想象的那样。原因不明,哪位高手能解读一下?

SQL-create-alter-drop-DDL

DDL 1. 数据库 * 查看所有数据库:SHOW  DATABASES * 切换(选择要操作的)数据库:USE 数据库名 * 创建数据库:CREATE  DATABASE [IF NOT EXISTS] mydb1 [CHARSET=utf8] * 删除数据库:DROP  DATABASE [IF EXISTS] mydb1 * 修改数据库编码:ALTER  DATABASE myd

Algorithm学习笔记 --- 小球下落问题(二叉树解法)

有一颗二叉树,最大深度为D,且所有的叶子深度都相同。所有的结点从上到下从左到右编号为 1,2,3,4,....,2^D-1.在结点1处放一个小球,它会往下落。每个结点上都有一个开关,初始全部关闭,当每次有小球落到一个开关上时,它的状态都会改变。当小球到达一个内结点时,如果该结点上的开关关闭,则往左走,否则往右走,知道走到叶子结点。 一些小球从结点1处开始下落,最后一个小球会落到哪里呢?输入叶子深

Algorithm学习笔记 --- 小球移动问题

此题用链表更加的方便一些。 你有一些小球,从左到右依次编号为1,2,3,…,n, 你可以执行两种指令。其中A X Y表示把小球X移动到小球Y左边,B X Y表示把小球X移动到小球Y右边。指令保证合法,即X不等于Y。 输入    小球个数n。指令条数m和m条指令,注意,1≤n≤500000,0≤m≤100000。 输出    从左到右输出最后的小球序列。