兩個組合優化問題及演算法

2021-08-04 05:00:12 字數 1999 閱讀 5103

最近看到兩道程式設計題,有點意思,不過網上看了一下,雖然有一些人寫出了演算法,但是感覺演算法思想表述的都不夠清晰,特別是都是直接上結論,然後證明這麼做是對的。

我不大喜歡這種表述方式,嘗試著以更容易理解的"順向思維",沒錯,不是什麼"逆向思維",就是正常的思路來推導一下求解過程.

①把陣列排成最小的數

輸入乙個正整數陣列,將它們連線起來排成乙個數,輸出能排出的所有數字中最小的乙個。例如輸入陣列,則輸出這兩個能排成的最小數字32132。

已經給出了演算法過程,並且證明了演算法是對的,這演算法就是定義

a與b的大小關係,若ab

那麼,我們是如何想到這種演算法的呢?

首先隨便寫出乙個方案,我們考察這個方案是否能夠優化,如果能應該怎麼做?

比如給定乙個方案bca,我們考慮這個數字能否通過優化變得更小呢?

考慮最簡單易行的優化方式----相鄰元素交換,如果bca的前兩位交換順序變為cba之後整個數字變小了,那麼應該滿足什麼條件呢?顯然,cb

倘若是最佳方案,由於最佳方案只有乙個,那麼這必須要求凡是按照這個原則,任意方案的調整最終都只能變為同乙個方案,這時很容易想起「氣泡排序法」,沒錯,無論什麼數列,按照氣泡排序都會變為遞增數列,但是氣泡排序法之所以可行,在於比較原則具有傳遞性,換言之,a

如果本問題中的比較原則也具有傳遞性,那麼任意方案按照「相鄰元素調整」的原則進行調整,最後的方案一定是像氣泡排序法一樣,"最小的元素"在最前邊,按順序排列,換言之,最終方案順序具有唯一性.

證明了本問題中的比較也是具有傳遞性的,換言之,若ab

這樣便可以證明,任意方案都可以在遵循我們制定的比較原則的前提下,通過相鄰調整,得到唯一的方案,而相鄰調整的過程中,數值是不斷變小的.也就是說,這個唯一方案的值小於任一方案.

那麼這個唯一方案就是最小的方案.

這問題是個組合優化問題,本質上是乙個排序問題。

②資源排程問題

有一台機器,上面有m個儲存空間。然後有n個請求,第i個請求計算時需要佔 r[i]個空間,儲存計算結果則需要佔據o[i]個空間(據o[i]個空間(其中o[i]

這個問題乍一看有點暈,差點準備用回溯法配合剪枝函式做了,不過那樣效率就相當低下了.

依然是考慮最優組合,okay,還是先給定乙個方案,a,b,c,d,e,考慮這個方案能否進一步優化?

依然是通過相鄰元素調整來進行優化嘗試,先說一下這個問題中,什麼叫「更優」,倘若方案a可行,而方案b不可行,那自然是a更優,不過這定義未免過於嚴格,很難這麼涇渭分明,一步達到,若ab都可行,那誰更優呢?

我們給出更優的定義:a可行的可能性比b大.

當然了,本問題也不是概率題,算不出各種方案的概率,這裡的可能性大的意思是,若a不可行則b必然不可行.則稱為a比b更優.

回到原方案,假設調整了i和j(這兩步是相鄰的),使得整個方案更優了,那麼我們需要考慮這要滿足什麼條件呢?

進行到i-1這一步的時候剩餘空間為m,那麼i,j可行意味著:m-o[i]>r[j],即o[i]+r[j]

調整為j,i之後,j之前的步驟沒有變化,所以剩餘空間還是m,那麼j,i可行意味著:m-o[j]>r[i],即

o[j]+r[i]

倘若變得更優了,即表示當j,i不可行的時候i,j一定不可行.

這意味著若o[j]+r[i]>m,一定有o[i]+r[j]>m.

i和j什麼條件能讓這件事情成為必然呢?顯然只要o[i]+r[j]>o[j]+r[i]即可,換言之,o[i]-r[i]>o[j]-r[j]即可,定義l[p]=o[p]-r[p],則l[i]>l[j]即可.

這麼一來就好辦了,把任意方案按照這個原則進行相鄰調整,得到的方案一定「越來越優秀」,與上乙個問題一樣,所有方案都這樣調整會「殊途同歸」嗎?

很顯然,本問題的這種比較原則具有傳遞性,即l[a]],l[b]

所以任一方案根據l[i]和l[j]的大小進行相鄰調整最終得到的方案一定是唯一的,那便是l值由小到大的排列順序的方案,若此方案不可行,其他方案一定不可行.

此方案即為最佳方案.

可以看到,以上這兩個問題其實都是利用相鄰元素調整,尋找其中的規律,來直接得到最優方案的,頗多相似之處,一旦找到規律,組合優化就變成了排序問題.

組合兩個表

表1 person 列名 型別 personid int firstname varchar lastname varchar personid 是上表主鍵 表2 address 列名 型別 addressid int personid int city varchar state varchar ...

leetcode mysql 組合兩個表

1 題目 表1 person 列名 型別 personid int firstname varchar lastname varchar personid 是上表主鍵 表2 address 列名 型別 addressid int personid int city varchar state var...

兩個有趣的演算法問題

2019年2月19日註 這篇文章原先發在自己github那邊的部落格,時間是2017年2月5日 一共是兩道題,第一道是上學期的matlab考試的時候碰到的,另外一道是師弟發的一道數學題的學習筆記,於是找了個時間想了一下,結合網上找到的資料參考。用的是matlab語言。1.乙隻青蛙,每次可以選擇跳1級...