法一:1 #include2 #include3
intmain()413
else
14 15}
16 printf("
%d\n
",k);17}
18 system("
pause");
19return0;
20 }
法二:1 #include2
intmain()
314 printf("
%d\n
",newvalue+base
);15}16
return0;
17}18 本題我是突然想到赫夫曼編碼,然後根據其意在題意所描述的滿二叉樹上編號,結果發現所得的二進位制編碼,除去最高位只保留深度數減一位,然後化為十進位制再加一,就是在這一層上葉子個數的序號,之後再加上這層之前所有的結點個數就是該葉子總的序號,也即是最後乙隻猴子所到的位置。而且最初得到的二進位制編碼,恰恰是最後那只猴子的序號減一所對應的二進位制數,注意所有的二進位制編碼位數都是深度減一!迴圈中用位運算效率較高!
演算法分析:剛看這題我就覺得這種題應該會有規律,想了一會還真有。令 a 為第 a 個出去的猴子; 如果 a 為偶數, 說明 a 所在的節點(設ans為 a 所在節點的值) 的開關是開著的,往右走 ans=ans*2+1 , a=a/2 ; 如果 a 為基數 則往左走 ans=ans*2 ,a=a/2+1.
思路:每個小球都會落在根節點上,因為前兩個小球必是乙個在左字數,乙個在右子樹。一般的,只需看小球編號的奇偶性,就能指導它是最終在哪棵子樹中。對於那些落入根結點左子樹的小球來說,只需知道小球是第幾個落在根是左子樹裡面的,就可以知道它下一步是往左還是往右了。依此類推,直至小球落在葉子上。
如果使用題目給出的i,當i是奇數時,它是往左走的第(i+1)/2個小球;當i是偶數時,它是往右走的第i/2個小球。這樣可以模擬最後乙個小球的路線。
解題思路:
很久前做過這道題,是用的模擬法做的。因為這道題數目的測試資料比較少,所以暴力就過了。
但是如果測試資料很大時,超時是明顯的。因為d<=20,所以需要遍歷的為2的19次方乘以19,如果有1000組測試資料,就肯定掛了。
今天看到了一種優化,非常巧妙。
因為每個小猴子都是從根節點向下,它必然有兩種選擇:左、右。而且有規律,它前面的兩個猴子一定是左,右。所以在每個節點進入根節點時,我們只需要判斷這個點的奇偶性就知道它的方向了。然後它進入根節點的下一層,依然有兩種選擇,同樣的判斷,但是資料規模減少一半(每進入1層,捨棄另乙個子樹,必然減少一半,因為左右的個數相同或者相差1),這樣,我們只需要判斷這個猴子是第幾個進入該層,然後判斷奇偶即可。
今天在看二叉樹,忽然發現有個題是跟二叉樹扯點邊,就順手把它做了。回過頭來看這個問題,會發現其實這個題真的很簡單。當初之所以沒有做而是放到了現在,就是自己犯了想當然的錯誤,認為這個題是乙個要用到二叉樹的題,自己沒有看二叉樹,肯定做不出來。就把它放到一邊了····實踐證明,這是一道水題·····一次直接水過。以前想的很麻煩,但是後來發現其實這個題很簡單。思路也很清晰。不斷的模擬小猴子在各個結點的選擇。先對輸入的小猴子的m編號進行判斷,如果它是奇數,那麼它就是第(m+1)/2個小猴子,那麼它的編號就是2k;偶數的話就是第m/2個小猴子。
NYOJ 63 小猴子下落
時間限制 3000 ms 記憶體限制 65535 kb 難度 3 描述 有一顆二叉樹,最大深度為d,且所有葉子的深度都相同。所有結點從左到右從上到下的編號為1,2,3,2的d次方減1。在結點1處放乙個小猴子,它會往下跑。每個內結點上都有乙個開關,初始全部關閉,當每次有小猴子跑到乙個開關上時,它的狀態...
NYOJ 63 小猴子下落
時間限制 3000 ms 記憶體限制 65535 kb 難度 3 描述 有一顆二叉樹,最大深度為d,且所有葉子的深度都相同。所有結點從左到右從上到下的編號為1,2,3,2的d次方減1。在結點1處放乙個小猴子,它會往下跑。每個內結點上都有乙個開關,初始全部關閉,當每次有小猴子跑到乙個開關上時,它的狀態...
NYOJ 63 小猴子下落
時間限制 3000 ms 記憶體限制 65535 kb 難度 3 描述 有一顆二叉樹,最大深度為d,且所有葉子的深度都相同。所有結點從左到右從上到下的編號為1,2,3,2的d次方減1。在結點1處放乙個小猴子,它會往下跑。每個內結點上都有乙個開關,初始全部關閉,當每次有小猴子跑到乙個開關上時,它的狀態...