程式設計 Fence Repair

2021-07-24 12:01:47 字數 1212 閱讀 6618

問題描述:農夫約翰為了修理柵欄,要將一塊很長的木板切割成n塊。準備切成的木板長度為l1、l2、···、ln,未切割之前木板的長度恰好為切割後木板長度的總和。每次切割木板時,需要的開銷為這塊木板的長度。例如長度為21 的木板要切成長度為5、8、8的三塊木板。長21的木板切成長為13和8的板時,開銷為21.再將長度為13的板切成長度為5和8 的板時,開銷是13.於是合計開銷為34。請求出按照目標要求將木板切割完最小的開銷是多少。(1<=n<=20000,0<=li<=50000)

輸入樣例:

n=3,l=(8,5,8)

輸出 34

思路:

我們可以建一棵二叉樹來表示切割的過程:

按照題意開銷計算為15+7+8+3=33,但是算不好,因為我們需要找開銷關於葉節點的計算,這樣方便我們設計演算法寫**。分析可以發現葉節點的深度對應於為了得到對應木板所需的切割次數,開銷的合計就是各葉節點的 木板長度 * 節點深度 的總和。上面的例子的開銷可以計算為:3*2+4*2+5*2+1*3+2*3=33

到了這裡,我們需要找到切割消耗最少的開銷,於是我們需要使得越短的板深度越深(或者說最短的板和次短的板應當是兄弟節點),所以用到了貪心演算法。對於最優解來說,一定存在的情況是:最短的板應當是深度最大的葉節點之一。這個葉節點的兄弟節點是一定存在的,並且由於是同一深度的葉節點,所以對應於次短的板。

假設li按照由小到大的順序排列好,那麼l1和l2是最小的板,且他們由乙個(l1+l2)長的板切割過來,將(l1和l2)放入序列中,再找該次切割前最小的板和次小的板,即在(l1+l2),l3,l4,···,ln一共n-1塊板中找,以此遞迴。

**部分:

typedef

long

long l1;

//輸入

int n,l[max_n];

void solve()

else

if(l[i]//將兩塊板拼合

int t = l[mii1] + l[mii2];

ans += t;

if(mii == n-1) swap(mii1,mii2);

l[mii1] = t;

l[mii2] = l[n-1];

n--;

}printf("%lld\n", ans);

}

Fence Repair 柵欄分割

rence repair 題目 農夫約翰為了修理柵欄,要將一塊很長的木板分割成n塊。準備切成的木板的長度為l1 l2 ln.未切割木板的長度恰好為切割木板的長度和。每次切斷木板時,需要的開銷為這塊木板的長度。例如,長度為21的木板切割成5 8 8的三塊木板。長為21的木板切割成13 8時,開銷為21...

優先佇列(和fence repair完全一樣)

時間限制 3000 ms 記憶體限制 65535 kb 難度 3 描述小明很想吃果子,正好果園果子熟了。在果園裡,小明已經將所有的果子打了下來,而且按果子的不同種類分成了不同的堆。小明決定把所有的果子合成一堆。因為小明比較懶,為了省力氣,小明開始想點子了 每一次合併,小明可以把兩堆果子合併到一起,消...

程式設計,還是程式設計

喜歡程式設計,雖然水平一般,但還是執著地學習與程式設計有關的知識。中間因為工作關係與程式設計遠離了一段時間,現在又重拾起來,細想起來還是因為喜歡吧。喜歡程式軟體的思想和原理,喜歡程式 的魅力和成就感。程式設計軟體的思想是最值得學習的,一直認為思想決定行動,思想改變世界。每種軟體的流行和受人追捧,無不...