愛奇藝2018.9.28筆試 散散的樹
阿新 • • 發佈:2018-12-12
題目描述
輸入: 5 20 4 42 40 26 46 輸出: 36
鋸子必須同時砍樹; 從樹頂到鋸子這段距離被砍下來當成木頭,從樹根到鋸子這段距離留下原地。 問鋸子最高可以多高,但其實要剛好使砍下來的木頭的總長為m,其實就只有一種鋸子的高度能滿足。
排序後遍歷
n,m = map(int,input().split())
li = list(map(int,input().split()))
li = sorted(li,reverse=True)#降序排序
li.append(0)#這樣就能砍到最矮的樹
Times = 1#倍數
result = 0#已經砍下的木頭的總長
if len(li) == 1:#只有一棵樹
print(li[0] - m)
elif len(li) > 1:
for i in range(1,len(li)):
temp = (li[i-1] - li[i]) * Times
tempResult = result + temp
if tempResult >= m:
if (m-result)%Times == 0:
last = (m-result)//Times
else:
last = (m-result)/Times
print(li[i-1]-last)
break
else:
result = tempResult
Times += 1
如上圖所示,以樣例輸入為例。 排降序後,黑色數字就是5顆樹。 紅色數字代表相鄰兩棵樹之間的高度差,藍色數字代表在這個區間內可以砍到幾棵樹。 比如,如果鋸子高度為42,那麼只能鋸下長度為4的木頭,而這樣的木頭只有1根。而如果鋸子高度為40,那麼除了之前鋸下的4*1的木頭,還有2*2的木頭可以鋸下。 黃色數字,說明了這個累加的過程。 由於8<20<50,所以鋸子的高度肯定是在[40,26]這個區間內。
演算法的思想是:
每次迴圈中,考慮鋸子的高度為li[i],那麼此時鋸子能鋸到從li[0]到li[i-1]這幾棵樹(li[i]這棵樹剛好鋸不到),然後算出當前鋸子能砍下的木頭的總長:
1.如果這個總長還是小於m,那麼i++,繼續迴圈。
2.如果這個總長大於等於m,那麼迴圈停止。然後根據當前的i,計算鋸子的高度。具體地來說:使用上一次迴圈i-1
用的鋸子所能砍下的樹的總長result
,m-result
就是剩餘需要砍下來的木頭長度。Times
就是當前能砍到幾棵樹。
前面的每次迴圈,代表區間[ li[i-1] , li[i] ]的樹都被完全砍掉了。
最後一次迴圈i中,代表區間[ li[i-1] , li[i] ]的樹不是被完全砍掉的。因此用m-result
除以Times
就是當前區間需要砍掉的每根木頭的長度last
。last
是可能為小數的,需要注意。
最終結果便是,li[i-1]-last
。