小球下落 UVa 679

2022-06-09 02:06:10 字數 1744 閱讀 1962

問題描述:

有一棵二叉樹,最大深度為d,且所有葉子的深度都相同。所有結點從上到下從左到右編號為1, 2, 3,…, 2d-1。在結點1處放乙個小球,它會往下落。每個內結點上都有乙個開關,初始全部關閉,當每次有小球落到乙個開關上時,狀態都會改變。當小球到達乙個內結點時,如果該結點上的開關關閉,則往左走,否則往右走,直到走到葉子結點,如圖6-2所示。

一些小球從結點1處依次開始下落,最後乙個小球將會落到**呢?輸入葉子深度d和小球個數i,輸出第i個小球最後所在的葉子編號。假設i不超過整棵樹的葉子個數。d≤20。輸入最多包含1000組資料。

樣例輸入:

4 23 4

10 1

2 28 128

16 12345

樣例輸出:127

5123

25536358

#include "iostream"

#include "cstdio"

#include "cmath"

#define max_node_cnt 1048576

using namespace std;

int d,i;

int state_tree[max_node_cnt + 1];

int right(int i)

int left(int i)

void clear(int i)

// 小球下落,返回葉子節點的值

int go(int i)

int main()

printf("%d\n", r);

}return 0;

}

如上的**的確能得出正確的結果,但是,每次尋找乙個葉子節點需要d-1個節點。然後,葉子節點的個數為2^d-1個,也就是i最大有2^d-1個。輸入最多有1000個,所以程式可能要算個1000*(d-1)*(2^d-1)次才能出結果,淦!!!

考慮對於根節點,第乙個小球會向左子樹那邊滾,第二個小球會向右子樹那邊滾。

把條件放的更寬一點,對於根節點,如果是第奇數個小球,那麼這個小球最後必定落到左子樹上,如果是第偶數個小球,那麼它必定落在右子樹上。

當第乙個小球從根節點落到節點2時,我們又可以把2看作根節點。

對於第n個經過節點2的小球,如果i是奇數,那麼它必定出現在節點2的左子樹,否則必定出現在節點2的右子樹。

遞迴下去,對每個節點都是這樣,關鍵我們要找到這個n,即第幾個通過節點x的小球。

對於根節點,這個數就是i。然後對於根的左子節點,第i個小球是第i+1/2個經過這個節點的小球,而對於右子節點,則是第i/2個經過這個節點的小球。

**

int main()  

else

printf("%d\n", k);

}}

UVa679 小球下落(樹)

給下落的深度和小球個數,小球依次下落,結點有個開關,每到乙個結點,開關關向左,開向右 一開始想到了簡單模擬,結果超時 include include include define maxn 20 using namespace std int s 1 printf d n now 2 return ...

23 小球下落(UVa679)

有一棵二叉樹,最大深度為d,且所有的葉子深度都相同。所有結點從上到下從左到右編號為1,2 3,2d 11,2,3,2 d 1 1,2,3,2d 1。在結點1處放乙個小球,它會往下落。每個結點上都有乙個開關,初始全部關閉,當每次有小球落到乙個開關上時,它的狀態都會改變。當小球到達乙個內結點時,如果該結...

UVa 679 小球下落 二叉樹的編號

在結點1處放乙個小球,它會往下落。每個內結點上都會有乙個開關,初始全部關閉,當每次有小球落到乙個開關上時,狀態都會改變。當小球到達乙個結點是,如果結點上的開關關閉,則往左走,否則往右走,直到走到葉子的結點,如圖。分析 對於乙個結點k,其左結點和右結點分別為2k和2k 1。小球落到結點處,先改變,後選...