算法竞赛入门经典:第六章 数据结构基础 6.5小球下落
2015-08-17 19:52
656 查看
/* 小球下落: 一颗二叉树,最大深度为D,且所有叶子的深度都相同。所有节点从上到下,从左到右编号为1,2,3...,2^D-1。在节点1处放一个小球,它会往下落。每个内节点上 都有一个开关,初始全部关闭,当每次有小球落到一个开关上时,它的状态都会改变。当小球到达一个内节点时,如果该节点上的开关关闭,则往左走,否则,往右 走,知道走到叶子节点,如图所示: 一些小球从节点1处一次开始下落,最后一个小球将会落到哪里呢?输入叶子深度D和小球个数I,输出第I个小球最后所在的叶子编号。假设I不超过整棵树的叶子个数 。D<=20,输入最多包含1000组数据。 输入: 4 2 3 4 10 1 2 2 8 128 16 12345 输出: 12 7 512 3 255 36358 关键: 1先建立二叉树,每走一次,改变开关,这可以用结构体里面的一个变量实现 */ #include <stdio.h> #include <stdlib.h> #include <queue> #include <math.h> #define MAXN 20 using namespace std; typedef struct Node { Node():flag(false){} int iData;//存放数字 bool flag;//开关默认是关闭的 struct Node* left,*right;//左孩子与右孩子 }Node,*binTree; void buildTree(binTree tree,int D) { queue<Node*> queueNode; queueNode.push(tree); Node* node; int iSum = floor(pow(2.0,D*1.0) + 0.5) - 1; while(!queueNode.empty() && D--) { node = queueNode.front(); queueNode.pop(); if((node->iData) <= ((iSum -1)/2) ) { Node* leftNode = (Node*)malloc(sizeof(Node)); leftNode->iData = 2*(node->iData); Node* rightNode = (Node*)malloc(sizeof(Node)); rightNode->iData = 2*(node->iData) + 1; queueNode.push(leftNode); queueNode.push(rightNode); } } } int ballDown(int D,int I) { binTree tree = (binTree)malloc(sizeof(Node)); tree->iData = 1; buildTree(tree,D); Node* node; for(int i = 1 ; i <= I; i++) { node = tree; int k = D; while(k--) { if(node->flag == false)//关,走到左孩子 { node->flag = true; node = node->left; } else { node->flag = false; node = node->right; } } printf("%d\n",node->iData); } return node->iData; } //关键:可以用数组模拟 int iBallArr[1<<MAXN]; int ballDown_array(int D,int I) { int iMax = (1<<D) - 1; int k; memset(iBallArr,0,sizeof(iBallArr)); for(int i = 0 ; i < I; i++) { k = 1; for(; ;) { iBallArr[k] = !iBallArr[k]; k = iBallArr[k] ? 2*k : (2*k + 1); if(k > iMax) { break; } } } printf("%d\n",k/2); return k/2; } int ballDown_simple(int D,int I) { int k = 1; for(int i = 0;i < D-1 ;i++)//经过D-1趟可确认最后一个球的位置 { if(I%2 == 0)//I为偶数,向右走,先左后右,然后向左孩子走,接下来I会变成奇数 { k = 2*k; I = (I+1)/2;//? } else { k = 2*k + 1; I /= 2; } } printf("%d\n",k); return k; } int main(int argc,char* argv[]) { int D,I; while(EOF != scanf("%d %d",&D,&I)) { //printf("%d\n",ballDown(D,I)); ballDown_array(D,I); //ballDown_simple(D,I); } system("pause"); return 0; }
相关文章推荐
- 算法竞赛入门经典:第六章 数据结构基础 6.4测试
- 算法竞赛入门经典:第六章 数据结构基础 6.3移动小球
- 算法竞赛入门经典:第六章 数据结构基础 6.2铁轨
- 算法竞赛入门经典:第六章 数据结构基础 6.1卡片游戏
- 数据结构实验:连通分量个数
- HashMap的数据结构
- 黑马程序员——JAVA之大话数据结构
- 第1章 数据结构绪论
- Codeforces Round #316 (Div. 2) E. Pig and Palindromes (DP)
- 数据结构:倒排索引
- Treap 模板
- 数据结构实验之栈二:一般算术表达式转换成后缀式 SDUT 2132
- 数据结构 二路归并排序的实现
- POJ 3750 小孩报数问题 数据结构水
- 《数据结构与算法分析——c语言描述》读后笔记 7
- 使用逆波兰式(后缀表达式)实现多功能计算器
- 数据结构:快状链表(数组链表联合)
- 数据结构 字符串二分查找正确实现
- 数据结构-二叉搜索树(Binary Search Tree)的C++实现模板
- 数据结构之二叉树的遍历