我們要對華容道問題求解首先要判斷這個問題是否有解。這里我們給出以下結論
數字華容道,必然有解,只存在於如下3個細分情形:
1.若格子列數為奇數,則逆序數必須為偶數;
2.若格子列數為偶數,且逆序數為偶數,則當前空格所在行數與初始空格所在行數的差為偶數;
3.若格子列數為偶數,且逆序數為奇數,則當前空格所在行數與初始空格所在行數的差為奇數。
轉自:https://www.jianshu.com/p/1c1849d876b2
當我們判斷我們的輸入有解后我們采用A*算法求解。
A*算法的核心可以用一個函數來表示 f(n)=g(n)+h(n)
其中g(n)表示我們實際的損失,具體的在這里表示我們目前已經走了幾步,這個是非常具體的,因為你走了幾步就是幾步。
h(n)表示的是我們預估我們從目前的狀態到達目標的狀態的損失的一個函數h,這是我們人為設定的,而對於所有的情況我們都只能通過我們設定的這一個函數h來預算,意思就是我們在第1步的時候通過一個確定的函數h來計算損失,那么第2步我們也只能通過這個函數h來計算損失,不能改變這個函數h。由於函數h是我們認為設定的,所以我們設定的函數h往往決定了我們得到結果的快慢。
我們的目標是用盡量少的步數來得到結果123 456 780,0表示沒有數字的格子。
當我們得到了一個輸入后,我們可以有四個選擇,即讓0與上下左右位交換(當然是要考慮越界,也就是碰牆的情況),對於得到的結果我們計算f(n),之后我們總是尋找一個最小的f(n)來拓展節點直到我們得到目標函數或者無解(其實就是找遍了所有的可能都找不到解)。而對於起始輸入以及拓展后不屬於已經計算過的結果我們加入open表,對於已經計算過的結果我們放入close表,之前說到的尋找最小的f也是在open表中尋找。
下面來試着從輸入到輸出開始說起,我們得到一個輸入,我們輸入放入open表,計算open表中損失f最小的節點,我們拓展該節點,將原始結點移出open表放入close表,對於拓展的節點我們判斷其是否是結果,若不是則判斷其是否已在close表,若沒有在close表,我們判斷其知否在open表,若不在open表中我們就將其加入到open表,若在open表就不加入(無需判斷,因為我們總是從最小的step出發,在h(n)相同的情況下,首先出現的肯定是最小的step)。之后我們尋找open表中損失f最小的節點,重復上面的操作就能得到結果。(這里忽略了一開始就是最終解的情況,實際上我們需要判斷輸入是否已經是最終解)
由於網上找不到目標是123 456 780的圖,故這里給出的是目標是123 804 765的圖(僅供參考,思路是一樣的)

因為是很久以前完成的小程序了,以前只懂python,所以這里只給出python版
輸入規則例子:按回車426按回車153按回車780
github:https://github.com/a892574222/Artificial-Intelligence/tree/master/Eight%20Puzzles