NYOJ 63-小猴子下落(二叉樹)
阿新 • • 發佈:2019-01-01
63-小猴子下落
題目描述
有一顆二叉樹,最大深度為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
思路1
- 深度為D的滿二叉樹,結點數為2^D-1;
- 如果把結點從上到下從左到右編號為1,2,3…,則結點k的左右子結點編號分別為2k,2k+1。
- 記開關關閉為0,開啟為1
程式碼
#include<iostream>
#include<cstdio>
using namespace std;
const int maxd=20;
int s[1<<maxd]; //最大結點個數為2^maxd-1
int main()
{
int D,I;
while ((cin>>D>>I)&&(D!=0&&I!=0))
{
memset(s,0,sizeof(s));
int k,n=(1<<D)-1;
for(int i=0;i<I;i++)
{
k=1;
while(k<=n) //k>n時,越界
{
s[k] = !s[k];
k=s[k]?2*k:2*k+1;
}
}
cout<<k/2<<endl;
}
return 0;
}
思路2
每隻猴子都會落在根結點上,因此前兩隻猴子必然是一個在左子樹,一個在右子樹,對於那些落入根結點左子樹的猴子來說,只需要知道該猴子是第幾只落在根的左子樹裡,就可以知道它下一步往左還是往右走。
如果使用題目中給出的編號I,則當I是奇數時,它是往左走的第(I+1)/2個小球;當I是偶數時,它是往右走的第I/2個小球。
程式碼
#include<stdio.h>
int main()
{
int D,I;
while(scanf("%d%d",&D,&I)==2)
{
if(D==0&&I==0) break;
int k=1;
for(int i=0;i<D-1;i++)
{
if(I%2)
{
k=k*2;I=(I+1)/2;
}
else
{
k=k*2+1;I=I/2;
}
}
printf("%d\n",k);
}
return 0;
}