圖著色貪心演算法
❶ 甯哥敤鐨勭畻娉曠瓥鐣ュ寘鎷
甯哥敤鐨勭畻娉曠瓥鐣ュ寘鎷浠ヤ笅鍑犱釜鏂歸潰錛
1銆佽椽蹇冪畻娉曪細璐蹇冪畻娉曟槸涓縐嶅湪姣忎竴姝ラ夋嫨涓閮介噰鍙栧湪褰撳墠鐘舵佷笅鏈濂芥垨鏈浼橈紙鍗蟲渶鏈夊埄錛夌殑閫夋嫨錛屼粠鑰屽笇鏈涘艱嚧緇撴灉鏄鏈濂芥垨鏈浼樼殑綆楁硶銆傝椽蹇冪畻娉曠殑鎬濊礬鏄浠庨棶棰樼殑灞閮ㄦ渶浼樿В鍑哄彂錛屽敖鍙鑳藉湴瀹炵幇鍏ㄥ矓鏈浼樿В銆傝椽蹇冪畻娉曞苟涓嶄竴瀹氳兘寰楀埌鏈浼樿В錛屼絾瀹冨彲浠ュ湪澶氶」寮忔椂闂村唴瑙e喅璁稿氶棶棰橈紝濡傛渶灝忕敓鎴愭爲銆佹渶鐭璺寰勭瓑銆
2銆佺墿嫻侀嗗煙錛氬湪鐗╂祦棰嗗煙涓錛岀畻娉曠瓥鐣ュ彲浠ョ敤浜庝紭鍖栬繍杈撹礬綰褲侀檷浣庤繍杈撴垚鏈鍜屾彁楂樿繍杈撴晥鐜囥備緥濡傦紝閫氳繃鍔ㄦ佽勫垝綆楁硶錛屽彲浠ユ牴鎹璐х墿鐨勭洰鐨勫湴鍜岃繍杈撻渶奼傦紝鍚堢悊瀹夋帓璐х墿鐨勮呰澆鍜岃繍杈撹礬綰匡紝鎻愰珮榪愯緭鏁堢巼騫墮檷浣庢垚鏈銆
3銆佷漢宸ユ櫤鑳介嗗煙錛氱畻娉曠瓥鐣ユ槸浜哄伐鏅鴻兘棰嗗煙涓鐨勯噸瑕佺粍鎴愰儴鍒嗭紝鍙浠ョ敤浜庢満鍣ㄥ︿範銆佽嚜鐒惰璦澶勭悊銆佽$畻鏈鴻嗚夌瓑棰嗗煙銆備緥濡傦紝鍦ㄦ満鍣ㄥ︿範涓錛岄氳繃璐蹇冪畻娉曞拰鍔ㄦ佽勫垝綆楁硶絳夌瓥鐣ワ紝鍙浠ヨ緇冩ā鍨嬪苟浼樺寲妯″瀷鍙傛暟錛屾彁楂樻ā鍨嬬殑鍑嗙『鎬у拰娉涘寲鑳藉姏銆
❷ 貪心演算法之會場安排問題
三星演算法之間最好還是不要安排互相的問題,這樣不利於你們倆的關系的便有好。
❸ 程序員必須掌握的核心演算法
程序員掌握核心演算法,還不收錄
1、十大排序演算法
(1)簡單排序:插入排序、選擇排序、冒泡排序(必學)。
(2)分治排序:快速排序、歸並排序(必學,快速排序還要關注中軸的選取方式)。
(3)分配排序:桶排序、基數排序。
(4)樹狀排序:堆排序(必學)。
(5)其他:計數排序(必學)、希爾排序。
對干十大演算法的學習,假如你不大懂的話,那麼推薦你去看書,因為看了書,你可能不僅僅知道這個演算法怎麼寫,還能知道他是怎麼來的。推薦書籍是《演算法第四版》,這本書講的很詳細,而且配了很多圖演示,還是挺好懂的。
2、搜索與回溯演算法
(1)貪心演算法(必學);
(2)啟發式搜索演算法:A*尋路演算法(了解);
(3)地圖著沖猜爛色演算法、N 皇後問題、最優加工順序;
(4)旅行商問題。
這方便的只是都是一些演算法相關的,像貪心演算法的思想兆納,就必須學的了。建議通過刷題來學習,leetcode 直接專題刷。
3、動態規劃
(1)樹形DP:01背包問題;
(2)線性DP:最長公共子序列、最長公共子串;
(3)區間DP:矩陣最大值(和以及積);
(4)數位DP:數字游戲;
(5)狀態壓縮DP:旅行商。
這里建議先了解動態規劃是什麼,之後 leetcode專題刷,反正就一般上面這幾種題型。
4、字元匹配演算法
(1)正則表達式;
(2)模式匹配:KMP、Boyer-Moore。
5、流相關演算法
(1)最大流:最短增廣路、Dinic 演算法。
(2)最大流最小割:最大收益問題、方格取數問題。
(3)最小費用最大流:最小散漏費用路、消遣。
❹ 求一個演算法(貪心演算法)
貪心演算法
一、演算法思想
貪心法的基本思路:
——從問題的某一個初始解出發逐步逼近給定的目標,以盡可能快的地求得更好的解。當達到某演算法中的某一步不能再繼續前進時,演算法停止。
該演算法存在問題:
1. 不能保證求得的最後解是最佳的;
2. 不能用來求最大或最小解問題;
3. 只能求滿足某些約束條件的可行解的范圍。
實現該演算法的過程:
從問題的某一初始解出發;
while 能朝給定總目標前進一步 do
求出可行解的一個解元素;
由所有解元素組合成問題的一個可行解;
二、例題分析
1、[背包問題]有一個背包,背包容量是M=150。有7個物品,物品可以分割成任意大小。
要求盡可能讓裝入背包中的物品總價值最大,但不能超過總容量。
物品 A B C D E F G
重量 35 30 60 50 40 10 25
價值 10 40 30 50 35 40 30
分析:
目標函數: ∑pi最大
約束條件是裝入的物品總重量不超過背包容量:∑wi<=M( M=150)
(1)根據貪心的策略,每次挑選價值最大的物品裝入背包,得到的結果是否最優?
(2)每次挑選所佔重量最小的物品裝入是否能得到最優解?
(3)每次選取單位重量價值最大的物品,成為解本題的策略。 ?
值得注意的是,貪心演算法並不是完全不可以使用,貪心策略一旦經過證明成立後,它就是一種高效的演算法。
貪心演算法還是很常見的演算法之一,這是由於它簡單易行,構造貪心策略不是很困難。
可惜的是,它需要證明後才能真正運用到題目的演算法中。
一般來說,貪心演算法的證明圍繞著:整個問題的最優解一定由在貪心策略中存在的子問題的最優解得來的。
對於例題中的3種貪心策略,都是無法成立(無法被證明)的,解釋如下:
(1)貪心策略:選取價值最大者。反例:
W=30
物品:A B C
重量:28 12 12
價值:30 20 20
根據策略,首先選取物品A,接下來就無法再選取了,可是,選取B、C則更好。
(2)貪心策略:選取重量最小。它的反例與第一種策略的反例差不多。
(3)貪心策略:選取單位重量價值最大的物品。反例:
W=30
物品:A B C
重量:28 20 10
價值:28 20 10
根據策略,三種物品單位重量價值一樣,程序無法依據現有策略作出判斷,如果選擇A,則答案錯誤。
所以需要說明的是,貪心演算法可以與隨機化演算法一起使用,具體的例子就不再多舉了。(因為這一類演算法普及性不高,而且技術含量是非常高的,需要通過一些反例確定隨機的對象是什麼,隨機程度如何,但也是不能保證完全正確,只能是極大的幾率正確)
================================
三個經典的貪心演算法
有人說貪心演算法是最簡單的演算法,原因很簡單:你我其實都很貪,根本不用學。有人說貪心演算法是最復雜的演算法,原因也很簡單:這世上貪的人太多了,那輪到你我的份?
不論難度如何,貪心演算法都是一個很重要的演算法,我在網上N多Online Judge中的題目中,總結了三類較為常見,也十分經典的貪心演算法,發布在這兒Just For Fun。
(註:由於沒有現成的名字可用,這三種類型貪心演算法的名字都是我自己取的,如果你聽著別扭,請見諒。)
No 1.線段覆蓋(linescover)
題目大意:
在一維空間中告訴你N條線段的起始坐標與終止坐標,要求求出這些線段一共覆蓋了多大的長度。
解題思路:
將線段按其坐標進行排序(排序的具體方法:按起始坐標排,起始坐標相同的按終止坐標排,都是小在前大在後),使之依次遞增,並按順序分別編號為X(i),X(i).a代表其起始坐標,X(i).b代表其終止坐標。
然後按排好的順序依次處理:定義一個變數last記錄考慮到當前線段之時被線段覆蓋的最大的坐標值,再定義一個變數length記錄當前線段覆蓋的長度。對於後面的線段,我們把它看成由兩個部分組成,即把它分成last之前的線段和last之後的線段。(如果線段全部處在last之後,其last之前的部分不存在。)由於我們排過序,我們可以肯定當前考慮的線段X(i)其處在last之前的部分不會對length造成影響(因為X(i-1).b=last,X(i).a>=X(i-1).a,即X(i)在last之前的部分所處位置肯定被線段X(i-1)覆蓋過),所以會對length產生影響的即是X(i)處在last之後的部分。
所以我們可以依次對每條線段做如下處理:(初始化length為零,last為負無窮)
length+=X(i).b-last (X(i).a<=last 且 X(i).b>=last)
length+=X(i).b-X(i).a (X(i).a>last)
last=X(i).b;
最後length就為我們所需要的答案。
No 2.最優數對(bestpair)
題目大意:
按遞增的順序告訴你N個正整數和一個實數P,要求求出求出該數列中的比例最接近P的兩個數(保證絕對沒有兩個數使得其比值為P)。
解題思路:
定義兩個指針i和j,先初始化i=j=1,然後進行如下操作:
當code[j]/code[i]>p時,inc(j);
當code[j]/code[i]<p時,inc(i)。
記錄其中產生的最優值即為答案。
No 3.連續數之和最大值(maxsum)
題目大意:
給出一個長度為N的數列(數列中至少有一個正數),要求求出其中的連續數之和的最大值。(也可以加入a和b來限制連續數的長度不小於a且不大於b)。
解題思路:
先說不加限制的那種,定義一個統計變數tot,然後用循環進行如下操作:inc(tot,item) 其中如果出現tot<0的情況,則將tot賦值為0。在循環過程之中tot出現的最大值即為答案。
如果加入了限制條件的話,問題就變得難一些了(這句真的不是廢話)。為此我們先定義數組sum[i]來表示code[1]到code[i]之和(這樣的話code[a]~code[b]的和我們就可以用sum[b]-sum[a-1]來表示了。)。
再維護一個數組hash[i]來表示滿足條件的sum[a-1]的下標,並使之按遞增順序排列,這樣當前以第i的數為終止的數列的最大值肯定就是sum[i]-sum[hash[1]]。
現在我們來討論hash數組之中的數據需要滿足的條件和如何維護的具體問題:
當考慮到以第i個數為結尾時,hash[i]所表示的下標需要滿足的第一個條件就是題目規定的長度限制,我們需要實時的加入滿足長度規定的下標,刪除不符合要求的下標。其次,與不加限制條件時相同,若sum[i]-sum[hash[1]]的值小於零,則清空數組hash。
維護時可以這樣,當考慮到第i個數時,我們就將下標i-a+1加入到hash中,因為hash中原來已經排好序,因此我們我們可以用插入排序來維護hash的遞增性,然後我們考察hash[1],若hash[1]<i-b+1,則證明其已超出長度限制,我們就將其刪除,接著再考慮更新後的hash[1],如此重復直至找到一個滿足條件的hash[1]為止。
我們可以用鏈表來表示hash,這樣就可以減少數據加入和刪除時頻繁數據移動的時間消耗。
記錄下sum[i]-sum[hash[1]]的最大值即為答案。
❺ 貪心演算法及其應用
求解一個問題時有多個步驟,每個步驟都選擇當下最優的那個解,而不用考慮整體的最優解。通常,當我們面對的問題擁有以下特點的時候,就可以考慮使用貪心演算法。
比如,我們舉個例子,倉庫裡面總共有五種豆子,其對應的重量和總價值如下,現在我們有一個可以裝100KG重量的袋子,怎麼裝才能使得袋子中的豆子價值最大?
我們首先看看這個問題是否符合貪心演算法的使用場景?限制值是袋子100KG,期望值是袋子裡面的價值最高。所以是符合的。那麼我們嘗試著應用下貪心演算法的方法,每一個步驟都尋找當下的最優解,怎麼做呢?
把倉庫裡面的每種豆子價值除以重量,得出每種豆子的單價,那麼當下的最優解,肯定是盡可能最多地裝單價最貴的,也就是先把20KG的黃豆都裝上,然後再把30KG的綠豆都裝上,再裝50KG的紅豆,那麼此時正好裝滿袋子,總價值將是270元,這就是通過貪心演算法求解的答案。
貪心演算法的應用在這個問題上的求解是否是最優解需要一個很復雜的數學論證,我們不用那樣,只要心裡舉幾個例子,驗證下是否比它更好即可,如果舉不出例子,那麼就可以認為這就是最優解了。
雖然貪心演算法雖然在大部分實踐場景中都能得到最優解,但是並不能保證一定是最優解。比如在如下的有向帶權圖中尋找從S到T的最短路徑,那麼答案肯定就是S->A->E->T,總代價為1+4+4=9;
然而,實際上的最短路徑是S->B->D->T,總代價為6。
所以,不能所有這類問題都迷信貪心演算法的求解,但其作為一種演算法指導思想,還是很值得學習的。
除了以上袋子裝豆子的問題之外,還有很多應用場景。這種問題能否使用貪心演算法來解決的關鍵是你能否將問題轉換為貪心演算法適用的問題,即找到問題的限制值和期望值。
我們有m個糖果要分給n個孩子,n大於m,註定有的孩子不能分到糖果。其中,每個糖果的大小都不同,分別為S1,S2,S3...,Sm,每個孩子對糖果的需求也是不同的,為N1,N2,N3...,Nn,那麼我們如何分糖果,才能盡可能滿足最多數量孩子的需求?
這個問題中,限制值是糖果的數量m,期望值滿足最多的孩子需求。對於每個孩子,能用小的糖果滿足其需求,就不要用大的,避免浪費。所以我們可以給所有孩子的需求排個序,從需求最小的孩子開始,用剛好能滿足他的糖果來分給他,以此來分完所有的糖果。
我們有1元、5元、10元、20元、50元、100元紙幣各C1、C5、C10、C20、C50、C100張,現在要購買一個價值K元的東西,請問怎麼才能適用最少的紙幣?
這個問題應該不難,限制值是各個紙幣的張數,期望值是適用最少的紙幣。那麼我們就先用面值最大的100元去付錢,當再加一張100元就超過K時,就更換小面額的,直至正好為K元。
對於n個區間[L1,R1],[L2,R2]...[Ln,Rn],我們怎麼從中選出盡可能多的區間,使它們不相交?
我們需要把這個問題轉換為符合貪心演算法特點的問題,假設這么多區間的最左端點是Lmin,最右端點是Rmax,那麼問題就是在[Lmin,Rmax]中,選擇盡可能多的區間往裡面塞,並且保證它們不相交。這里,限制值就是區間[Lmin,Rmax],期望值就是盡可能多的區間。
我們的解決辦法就是每次從區間中選擇那種左端點>=已經覆蓋區間右邊端點的,且該區間右端點盡可能高小的。如此,我們可以讓未覆蓋區間盡可能地大,才能保證可以塞進去盡可能多的區間。
貪心演算法最重要的就是學會如何將要解決的問題抽象成適合貪心演算法特點的模型,找到限制條件和期望值,只要做好這一步,接下來的就比較簡單了。在平時我們不用刻意去記,多多練習類似的問題才是最有效的學習方法。