演算法設計 合併果子的兩種不同合併方式

2021-10-05 16:02:54 字數 1710 閱讀 5954

問題描述

不同應用背景分析

**及注釋總結

問題描述

目前有n堆果子,現在要將果子兩兩合併為一堆,每一次合併,可以把兩堆果子合併到一起

消耗的體力等於兩堆果子的重量之和。可以看出,所有的果子經過 n−1 次合併之後, 就只剩下一堆了。合併果子時總共消耗的體力等於每次合併所耗體力之和。假定每個果子重量都為 111 ,並且已知果子的堆 數和每堆果子的數目,你的任務是設計出合併的次序方案,使多多耗費的體力最少,並輸出這個最小的體力耗費值。

例如:有3堆果子,每堆數量分別是1,2,9.可以先將1,2合併,耗費體力為3,將新堆與原來的第三堆合併,得到新堆12,耗費體力12。所以耗費的總體力為15.

不同應用背景:

合併果子時,對合併操作更嚴格,要求每次只能合併相鄰兩堆果子。

合併果子時,對合併操作無要求,可以任意合併兩堆果子。

這兩種不同的問法,所對應的解題演算法和思路是完全不一樣的,讀者遇到題目時非常容易想當然,忽略細節。

第一種情況:涉及到區間dp,當只有兩堆時,毫無疑問直接合併;當有三堆果子時,此時的最優解依賴於兩種子問題(1.先合併第

一、二堆,再合併第三堆。2先合併第

二、三堆。再然後合併第一堆),當涉及更多堆果子時,依次類推。這樣滿足最優子結構性質,大問題最優依賴於很多小問題最優,考慮dp.用dp[i] [j]陣列記錄第i到第j堆的耗費的最少體力

dp公式:

i!=j,dp[i][j]=min(dp[i][k]+dp[k+1][j]+sum[i][j]

i==j dp[i][j]=0;

第二種情況:由於任意合併兩堆果子,貪心演算法非常明顯了,即每次合併數目最少的兩堆果子,重複操作n-1次。畫出結構圖,可以看出就是大頂堆的資料結構,考慮到每次操作都要找出最少和次少的果堆,我們就採用優先佇列的儲存結構,儲存資料。

**及注釋

任意相鄰:

#include

#include

using

namespace std;

intmain()

while

(q.size()

>1)

printf

("%d"

,sum)

;return0;

}

相鄰合併:

#include

#include

#define n 201

#define inf 0x3f3f3f3f

using

namespace std;

intmain()

//只有一堆時,無需合併

for(len=

1;len}printf

("%d\n"

,dp[1]

[n])

;return0;

}int

min(

int x,

int y)

總結:

學習程式設計,提高演算法能力,應注重歸納總結,學習完一門演算法之後,馬上找相應的題目上機練習,逐漸練就一題多解,舉一反三。

希望本例程對讀者有用並能激發你的思考,最後祝刷到這條部落格的朋友們,今年暴富,願望成真!

合併兩個陣列的兩種方式的異同

本文討論合併陣列的兩種方式 a b array merge a,b 操作符 在前乙個數的基礎上插入後乙個陣列,假設有同樣的拋棄,而array merge 是在前乙個引數基礎上插入後乙個引數。假設有同樣用的key 用後乙個覆蓋。實比例如以下 php a array a 1 b 2 c 3 php b ...

c語言的兩種排序方式(合併與快速)

合併排序 自定義型別 void swap type a,type b intpartition type a,int p,int r 把初始值換到中間,滿足演算法的思想 a p a j a j x return j void sort type a,int p,int r int main sort...

兩種不同的盒模型

邊框 border 外邊距 margin 內邊距 padding 元素的邊框就是圍繞在內容和內邊距的一條或多條線,它的屬性是border 邊框有三個屬性值1.寬度 2.樣式 3.顏色 border width style color 寬度樣式 solid 實線 dashed 虛線 dotted 點狀...