小球下落-二叉樹
有一顆二叉樹,最大深度為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-1
int 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:《演算法競賽入門經典》
相關文章
- 演算法競賽入門經典--紫書6.3.1小球下落演算法
- 滿二叉樹、完全二叉樹、平衡二叉樹、二叉搜尋樹(二叉查詢樹)和最優二叉樹二叉樹
- 二叉樹 & 二叉查詢樹二叉樹
- 排序二叉樹和平衡二叉樹排序二叉樹
- 二叉查詢樹(二叉排序樹)排序
- 二叉樹(順序儲存二叉樹,線索化二叉樹)二叉樹
- 手擼二叉樹——二叉查詢樹二叉樹
- 手擼二叉樹——AVL平衡二叉樹二叉樹
- 資料結構之樹結構概述(含滿二叉樹、完全二叉樹、平衡二叉樹、二叉搜尋樹、紅黑樹、B-樹、B+樹、B*樹)資料結構二叉樹
- 二叉樹二叉樹
- 二叉樹的應用(1)--二叉樹排序樹基本操作二叉樹排序
- 判斷二叉樹是否為滿二叉樹二叉樹
- 資料結構中的樹(二叉樹、二叉搜尋樹、AVL樹)資料結構二叉樹
- 自己動手作圖深入理解二叉樹、滿二叉樹及完全二叉樹二叉樹
- 二叉樹、B樹以及B+樹二叉樹
- 平衡二叉樹,B樹,B+樹二叉樹
- 深入學習二叉樹 (一) 二叉樹基礎二叉樹
- 相同二叉樹和鏡面二叉樹問題二叉樹
- 判斷某棵二叉樹是否二叉排序樹二叉樹排序
- 平衡二叉樹(AVL樹)和 二叉排序樹轉化為平衡二叉樹 及C語言實現二叉樹排序C語言
- 樹和二叉樹簡介二叉樹
- n叉樹vs二叉樹二叉樹
- Chapter 3 樹與二叉樹APT二叉樹
- 樹(2)--二叉樹的遍歷(非遞迴)+線索二叉樹二叉樹遞迴
- 迭代二叉樹二叉樹
- 二叉樹深度二叉樹
- 重建二叉樹二叉樹
- javascript二叉樹JavaScript二叉樹
- 平衡二叉樹二叉樹
- 二叉樹---深度二叉樹
- Java二叉樹Java二叉樹
- JS二叉樹JS二叉樹
- 二叉排序樹排序
- 二叉樹——高度二叉樹
- 12、二叉樹二叉樹
- 二叉蘋果樹蘋果
- 滿二叉樹二叉樹
- 二叉樹的子結構、深度以及重建二叉樹二叉樹