什麼是NP問題,什麼是NP hard問題,什麼是NP完全問題
假如老闆要你解決一個問題,你絞盡腦汁還是想不出來,叫天天不應,叫地地不靈,這時你走進老闆辦公室,可以採取3種策略:
1)
一副倒黴像,神情猥瑣,可憐巴巴的說:老闆,我沒做出來,我想我是太蠢了……
boss:蠢材!滾!
(失敗……)
2)
雄赳赳氣昂昂跨進老闆辦公室,大吼一聲:小樣,你丫給我問題根本就無解,害我白想這麼些天,我靠!
boss:我才靠,自己做不出來就說這個問題無解,要是人人都這樣混,我這老闆還當個屁阿,滾!
(做不出來還如此氣概,不僅失敗,而且欠扁……)
3)
從容不迫的說:老闆,我做不出來,但是,我敢肯定,那些大牛們也照樣做不出來。
boss:原來是這樣,那也難為你了。
雖然是一個笑話,但也可以為我們的生活研究提供一些思路和指導。當你面對一個問題解決不了時,那麼就試圖去證明別人也解決不了,這的確是一個偷懶逃避的好藉口。我覺得P、NP、NP-complete、NP-hard這些名稱的出現,就是因為某些難問題,連大牛們都解決不了,無可奈何之下,只好定義一堆東西,為自己找個理由,免得說自己太笨了。其實這是給出一個面對難解問題的解決思路,如果無法得到最優解,那麼先去嘗試驗證哪些解是不是最優解。
下面依次介紹:
一、計算複雜性
計算複雜性一般包括時間複雜度和空間複雜度,時間複雜度並不是某演算法實際執行需要的時間,而是漸進時間複雜度,即當問題規模趨向於無窮大時,該演算法時間複雜度的數量級。常見的時間複雜度,按數量級遞增排列依次為:常數階O(1)、對數階O(log2n)、線性階O(n)、線性對數階O(nlog2n)、平方階O(n^2)、立方階O(n^3)、k次方階O(n^k)、指數階O(2^n)。這裡用大O表示法來表述,給出的是演算法的最壞情況的時間代價。
複雜度關係:c < log2N < n < n * Log2N < n^2 < n^3 < 2^n < 3^n < n!
其中c是一個常量,如果一個演算法的複雜度為c 、 log2N 、n 、 n*log2N ,那麼這個演算法時間效率比較高,叫做多項式級的複雜度。如果是 2^n , 3^n ,n!,那麼稍微大一些的n就會令這個演算法不能動了,這些是非多項式級的,其複雜度計算機往往不能承受。當我們在解決一個問題時,我們選擇的演算法通常都需要是多項式級的複雜度,非多項式級的複雜度需要的時間太多,往往會超時,除非是資料規模非常小。
空間複雜度是指演算法在計算機內執行時所需儲存空間的度量。這裡不再細講。
自然地,人們會想到一個問題:會不會所有的問題都可以找到複雜度為多項式級的演算法呢?很遺憾,答案是否定的。有些問題甚至根本不可能找到一個正確的演算法來,這稱之為“不可解問題”(Undecidable Decision Problem)。
二、P問題(Polynomial Solvable)
定義:那些可以在多項式( polynomial )時間內解決的問題,稱為P問題。(或:如果一個問題可以找到一個能在多項式的時間裡解決它的演算法,那麼這個問題就屬於P問題。)
時間複雜度如(n^2, n^4, n(log(n)))都是多項式時間的,指數級別的如(2^n,n^n)這些就不是多項式時間了。
三、NP問題(Non-determinstic Polynomial Solvable)
定義:給定一個解,我們可以在多項式時間內檢查他正確與否的決策問題,為NP問題。
比如,我要找一個圖的哈密頓路徑,隨便給我一個解,我都可以在多項式時間內檢查它是不是哈密頓路徑。只要形如定義的問題,就是NP問題。
之所以要定義NP問題,是因為通常只有NP問題才可能找到多項式的演算法。我們不會指望一個連多項式地驗證一個解都不行的問題存在一個解決它的多項式級的演算法。相信讀者很快明白,資訊學中的號稱最困難的問題——“NP問題”,實際上是在探討NP問題與P類問題的關係。
很顯然,所有的P類問題都是NP問題。也就是說,能多項式地解決一個問題,必然能多項式地驗證一個問題的解——既然正解都出來了,驗證任意給定的解也只需要比較一下就可以了。關鍵是,人們想知道,是否所有的NP問題都是P類問題。我們可以再用集合的觀點來說明。如果把所有P類問題歸為一個集合P中,把所有 NP問題划進另一個集合NP中,那麼,顯然有P屬於NP。現在,所有對NP問題的研究都集中在一個問題上,即究竟是否有P=NP?通常所謂的“NP問題”,其實就一句話:證明或推翻P=NP。
目前為止這個問題還“啃不動”。但是,一個總的趨勢、一個大方向是有的。人們普遍認為,P=NP不成立,也就是說,多數人相信,存在至少一個不可能有多項式級複雜度的演算法的NP問題。人們如此堅信P≠NP是有原因的,就是在研究NP問題的過程中找出了一類非常特殊的NP問題叫做NP-complete問題,也即所謂的NPC問題。
四、歸約
為了說明NPC問題,我們先引入一個概念——約化(Reducibility,有的資料上叫“歸約”)。
簡單地說,一個問題A可以約化為問題B的含義即是,可以用問題B的解法解決問題A,或者說,問題A可以“變成”問題B。
“問題A可約化為問題B”有一個重要的直觀意義:B的時間複雜度高於或者等於A的時間複雜度。也就是說,問題A不比問題B難。這很容易理解。既然問題A能用問題B來解決,倘若B的時間複雜度比A的時間複雜度還低了,那A的演算法就可以改進為B的演算法,兩者的時間複雜度還是相同。
從約化的定義中我們看到,一個問題約化為另一個問題,時間複雜度增加了,問題的應用範圍也增大了。通過對某些問題的不斷約化,我們能夠不斷尋找複雜度更高,但應用範圍更廣的演算法來代替複雜度雖然低,但只能用於很小的一類問題的演算法。再回想前面講的P和NP問題,聯想起約化的傳遞性,自然地,我們會想問,如果不斷地約化上去,不斷找到能“通吃”若干小NP問題的一個稍複雜的大NP問題,那麼最後是否有可能找到一個時間複雜度最高,並且能“通吃”所有的 NP問題的這樣一個超級NP問題?答案居然是肯定的。也就是說,存在這樣一個NP問題,所有的NP問題都可以約化成它。換句話說,只要解決了這個問題,那麼所有的NP問題都解決了。這種問題的存在難以置信,並且更加不可思議的是,這種問題不只一個,它有很多個,它是一類問題。這一類問題就是傳說中的NPC 問題,也就是NP-完全問題。
五、NP-complete問題
定義:NP-c問題是這樣的一類問題,首先他是屬於NP的,而且他是NP問題裡面最難解決的問題。難到什麼程度?只要其中某個問題可以在P時間內解決,那麼所有的NP問題就都可以在P時間內解決了。
既然所有的NP問題都能約化成NPC問題,那麼只要任意一個NPC問題找到了一個多項式的演算法,那麼所有的NP問題都能用這個演算法解決了,NP也就等於P 了。因此,給NPC找一個多項式演算法太不可思議了。
“正是NPC問題的存在,使人們相信P≠NP”。我們可以就此直觀地理解,NPC問題目前沒有多項式的有效演算法,只能用指數級甚至階乘級複雜度的搜尋。
NP-c問題的定義出來了,但是,它忽悠了半天,除了說明這類問題比較難之外,其他啥也沒有。我們還是不知道到底什麼問題是NP-c問題,如何判定一個問題是不是NP-c問題。
1970年,cook同志發明了cook定理,找到了第一個NP-c問題,SAT(Satisfiability)問題(邏輯電路問題)。他是這麼說的,如果SAT問題可以在P時間解決,那麼所有的NP問題都可以在P時間內解決。
有了第一個NPC問題後,一大堆NPC問題就出現了,因為再證明一個新的NPC問題只需要將一個已知的NPC問題約化到它就行了。後來,Hamilton 迴路成了NPC問題,TSP問題也成了NPC問題,其他還有圖染色問題、揹包問題等。現在被證明是NPC問題的有很多,任何一個找到了多項式演算法的話所有的NP問題都可以完美解決了。因此說,正是因為NPC問題的存在,P=NP變得難以置信。
六、NP-hard問題
定義:NP-hard問題是這樣的問題,只要其中某個問題可以在P時間內解決,那麼所有的NP問題就都可以在P時間內解決了。NP-c問題就是NP-hard問題。但注意NP-hard問題它不一定是NP問題,比如,下圍棋就是NP-hard問題,但不是NP問題,我們要在一個殘局上找一個必勝下法,告訴我們下一步下在哪裡。顯然,我們找不這個解,而且更難的是,就算有人給我了一個解,我們也無法在P時間內判斷它是不是正確的。