演算法可能解
Ⅰ 演算法的重要特性有哪些呢
演算法的五個重要的特徵:確定性、可行性、輸入、輸出、有窮性/有限性。
演算法是解決「做什麼」和「怎麼做」的問題。解決一個問題可能有多種不同的演算法,從效率上考慮,其中最為核心的還是演算法的速度。因此,解決問題的步驟需要在有限的時間內完成,並且操作步驟中不可以有歧義性語句,以免後繼步驟無法繼續進行下去。通過對演算法概念的分析,可以總結出一個演算法必須滿足如下 5個特性。
(1)有窮性。一個演算法在執行有限步驟後,在有限時間內能夠實現的,就稱該演算法具有有窮性。
有的演算法在理論上滿足有窮性,在有限的步驟後能夠完成,但是計算機可能實際上會執行一天、一年、十年等等。演算法的核心就是速度,那麼這個演算法也就沒有意義了。總而言之,有窮性沒有特定的限度,取決於人們的需要。
(2)確定性。演算法中每一個步驟的表述都應該是確定的、沒有歧義的語句。在人們的日常生活中,遇到歧義性語句,可以根據常識、語境等理解,然而還有可能理解錯誤。計算機不比人腦,不會根據演算法的意義來揣測每一個步驟的意思,所以演算法的每一步都要有確定的含義。
(3)有零個或多個輸入。程序中的演算法和數據是相互聯系的。演算法中,需要輸入的是數據的量值。輸入可以是多個也可以是零個。其實,零個輸入並不是這個演算法沒有輸入,而是這個輸入沒有直觀地顯現出來,隱藏在演算法本身當中。
(4)有一個輸出或多個輸出。輸出就是演算法實現所得到的結果,是演算法經過數據加工處理後得到的結果。有的演算法輸出的是數值,有的是圖形,有的輸出並不是那麼顯而易見。沒有輸出的演算法是沒有意義的。
(5)可行性。演算法的可行性就是指每一個步驟都能夠有效地執行,並得到確定的結果,而且能夠用來方便地解決一類問題。
Ⅱ 什麼叫演算法演算法有哪幾種表示方法
演算法(Algorithm)是指解題方案的准確而完整的描述,是一系列解決問題的清晰指令,演算法代表著用系統的方法描述解決問題的策略機制。計算機科學家往往將「演算法」一詞的含義限定為此類「符號演算法」。「演算法」概念的初步定義:一個演算法是解決一個問題的進程。而並不需要每次都發明一個解決方案。
已知的演算法有很多,例如「分治法」、「枚舉測試法」、「貪心演算法」、「隨機演算法」等。
(2)演算法可能解擴展閱讀
演算法中的「分治法」
「分治法」是把一個復雜的問題拆分成兩個較為簡單的子問題,進而兩個子問題又可以分別拆分成另外兩個更簡單的子問題,以此類推。問題不斷被層層拆解。然後,子問題的解被逐層整合,構成了原問題的解。
高德納曾用過一個郵局分發信件的例子對「分治法」進行了解釋:信件根據不同城市區域被分進不同的袋子里;每個郵遞員負責投遞一個區域的信件,對應每棟樓,將自己負責的信件分裝進更小的袋子;每個大樓管理員再將小袋子里的信件分發給對應的公寓。
Ⅲ 幾種常用的演算法簡介
1、窮舉法窮舉法是最基本的演算法設計策略,其思想是列舉出問題所有的可能解,逐一進行判別,找出滿足條件的解。
窮舉法的運用關鍵在於解決兩個問題:
在運用窮舉法時,容易出現的問題是可能解過多,導致演算法效率很低,這就需要對列舉可能解的方法進行優化。
以題1041--純素數問題為例,從1000到9999都可以看作是可能解,可以通過對所有這些可能解逐一進行判別,找出其中的純素數,但只要稍作分析,就會發現其實可以大幅度地降低可能解的范圍。根據題意易知,個位只可能是3、5、7,再根據題意可知,可以在3、5、7的基礎上,先找出所有的二位純素數,再在二位純素數基礎上找出三位純素數,最後在三位純素數的基礎上找出所有的四位純素數。
2、分治法分治法也是應用非常廣泛的一種演算法設計策略,其思想是將問題分解為若乾子問題,從而可以遞歸地求解各子問題,再綜合出問題的解。
分治法的運用關鍵在於解決三個問題:
我們熟知的如漢諾塔問題、折半查找演算法、快速排序演算法等都是分治法運用的典型案例。
以題1045--Square Coins為例,先對題意進行分析,可設一個函數f(m, n)等於用面值不超過n2的貨幣構成總值為m的方案數,則容易推導出:
f(m, n) = f(m-0*n*n, n-1)+f(m-1*n*n, n-1)+f(m-2*n*n, n-1)+...+f(m-k*n*n, n-1)
這里的k是幣值為n2的貨幣最多可以用多少枚,即k=m/(n*n)。
也很容易分析出,f(m, 1) = f(1, n) = 1
對於這樣的題目,一旦分析出了遞推公式,程序就非常好寫了。所以在動手開始寫程序之前,分析工作做得越徹底,邏輯描述越准確、簡潔,寫起程序來就會越容易。
3、動態規劃法
動態規劃法多用來計算最優問題,動態規劃法與分治法的基本思想是一致的,但處理的手法不同。動態規劃法在運用時,要先對問題的分治規律進行分析,找出終結子問題,以及子問題向父問題歸納的規則,而演算法則直接從終結子問題開始求解,逐層向上歸納,直到歸納出原問題的解。
動態規劃法多用於在分治過程中,子問題可能重復出現的情況,在這種情況下,如果按照常規的分治法,自上向下分治求解,則重復出現的子問題就會被重復地求解,從而增大了冗餘計算量,降低了求解效率。而採用動態規劃法,自底向上求解,每個子問題只計算一次,就可以避免這種重復的求解了。
動態規劃法還有另外一種實現形式,即備忘錄法。備忘錄的基本思想是設立一個稱為備忘錄的容器,記錄已經求得解的子問題及其解。仍然採用與分治法相同的自上向下分治求解的策略,只是對每一個分解出的子問題,先在備忘錄中查找該子問題,如果備忘錄中已經存在該子問題,則不須再求解,可以從備忘錄中直接得到解,否則,對子問題遞歸求解,且每求得一個子問題的解,都將子問題及解存入備忘錄中。
例如,在題1045--Square Coins中,可以採用分治法求解,也可以採用動態規劃法求解,即從f(m, 1)和f(1, n)出發,逐層向上計算,直到求得f(m, n)。
在競賽中,動態規劃和備忘錄的思想還可以有另一種用法。有些題目中的可能問題數是有限的,而在一次運行中可能需要計算多個測試用例,可以採用備忘錄的方法,預先將所有的問題的解記錄下來,然後輸入一個測試用例,就查備忘錄,直接找到答案輸出。這在各問題之間存在父子關系的情況下,會更有效。例如,在題1045--Square Coins中,題目中已經指出了最大的目標幣值不超過300,也就是說問題數只有300個,而且各問題的計算中存在重疊的子問題,可以採用動態規劃法,將所有問題的解先全部計算出來,再依次輸入測試用例數據,並直接輸出答案。
4、回溯法回溯法是基於問題狀態樹搜索的求解法,其可適用范圍很廣。從某種角度上說,可以把回溯法看作是優化了的窮舉法。回溯法的基本思想是逐步構造問題的可能解,一邊構造,一邊用約束條件進行判別,一旦發現已經不可能構造出滿足條件的解了,則退回上一步構造過程,重新進行構造。這個退回的過程,就稱之為回溯。
回溯法在運用時,要解決的關鍵問題在於:
回溯法的經典案例也很多,例如全排列問題、N後問題等。
5、貪心法貪心法也是求解最優問題的常用演算法策略,利用貪心法策略所設計的演算法,通常效率較高,演算法簡單。貪心法的基本思想是對問題做出目前看來最好的選擇,即貪心選擇,並使問題轉化為規模更小的子問題。如此迭代,直到子問題可以直接求解。
基於貪心法的經典演算法例如:哈夫曼演算法、最小生成樹演算法、最短路徑演算法等。
Ⅳ 演演算法的n 皇後問題是否必然有解,理由是什麼 研究好久到處爬文還是搞不太懂QAQ 謝謝!!
N皇後問題是一個經典的問題,在一個N*N的棋盤上放置N個皇後,每行一個並使其不能互相攻擊(同一行、同一列、同一斜線上的皇後都會自動攻擊)。
一、 求解N皇後問題是演算法中回溯法應用的一個經典案例
回溯演算法也叫試探法,它是一種系統地搜索問題的解的方法。回溯演算法的基本思想是:從一條路往前走,能進則進,不能進則退回來,換一條路再試。
在現實中,有很多問題往往需要我們把其所有可能窮舉出來,然後從中找出滿足某種要求的可能或最優的情況,從而得到整個問題的解。回溯演算法就是解決這種問題的「通用演算法」,有「萬能演算法」之稱。N皇後問題在N增大時就是這樣一個解空間很大的問題,所以比較適合用這種方法求解。這也是N皇後問題的傳統解法,很經典。
下面是演算法的高級偽碼描述,這里用一個N*N的矩陣來存儲棋盤:
1) 演算法開始, 清空棋盤,當前行設為第一行,當前列設為第一列
2) 在當前行,當前列的位置上判斷是否滿足條件(即保證經過這一點的行,列與斜線上都沒有兩個皇後),若不滿足,跳到第4步
3) 在當前位置上滿足條件的情形:
在當前位置放一個皇後,若當前行是最後一行,記錄一個解;
若當前行不是最後一行,當前行設為下一行, 當前列設為當前行的第一個待測位置;
若當前行是最後一行,當前列不是最後一列,當前列設為下一列;
若當前行是最後一行,當前列是最後一列,回溯,即清空當前行及以下各行的棋盤,然後,當前行設為上一行,當前列設為當前行的下一個待測位置;
以上返回到第2步
4) 在當前位置上不滿足條件的情形:
若當前列不是最後一列,當前列設為下一列,返回到第2步;
若當前列是最後一列了,回溯,即,若當前行已經是第一行了,演算法退出,否則,清空當前行及以下各行的棋盤,然後,當前行設為上一行,當前列設為當前行的下一個待測位置,返回到第2步;
演算法的基本原理是上面這個樣子,但不同的是用的數據結構不同,檢查某個位置是否滿足條件的方法也不同。為了提高效率,有各種優化策略,如多線程,多分配內存表示棋盤等。
在具體解決該問題時,可以將其拆分為幾個小問題。首先就是在棋盤上如何判斷兩個皇後是否能夠相互攻擊,在最初接觸這個問題時,首先想到的方法就是把棋盤存儲為一個二維數組,然後在需要在第i行第j列放置皇後時,根據問題的描述,首先判斷是在第i行是否有皇後,由於每行只有一個皇後,這個判斷也可以省略,然後判斷第j列是否有皇後,這個也很簡單,最後需要判斷在同一斜線上是否有皇後,按照該方法需要判斷兩次,正對角線方向和負對角線方向,總體來說也不難。但是寫完之後,總感覺很笨,因為在N皇後問題中這個函數的使用次數太多了,而這樣做效率較差,個人感覺很不爽。上網查看了別人的實現之後大吃一驚,大牛們都是使用一個一維數組來存儲棋盤,在某個位置上是否有皇後可以相互攻擊的判斷也很簡單。具體細節如下:
把棋盤存儲為一個N維數組a[N],數組中第i個元素的值代表第i行的皇後位置,這樣便可以把問題的空間規模壓縮為一維O(N),在判斷是否沖突時也很簡單,首先每行只有一個皇後,且在數組中只佔據一個元素的位置,行沖突就不存在了,其次是列沖突,判斷一下是否有a[i]與當前要放置皇後的列j相等即可。至於斜線沖突,通過觀察可以發現所有在斜線上沖突的皇後的位置都有規律即它們所在的行列互減的絕對值相等,即| row – i | = | col – a[i] | 。這樣某個位置是否可以放置皇後的問題已經解決。