八數碼問題

2021-08-30 12:19:00 字數 4075 閱讀 5124

搜尋演算法學問不小...

總結:1. 狀態表示用整數最快, 可是轉化狀態的**不好寫, 用字串挺爽的, 可有些地方涉及到數字運算, **又不自然, 整來整去, 還是用byte好了...效能沒比字串強多少...

2. open錶用linkedlist就挺好, 支援佇列和堆疊兩種模型, 這點在雙向廣度優先搜尋時候挺方便, closed表千萬別用list型別, 用hashmap或者hashset效能上才可接受, 而且前者優於後者...

3. 完美雜湊函式, 也就是那個全排列的雜湊函式, 能夠不浪費一點兒空間, 實現一一對映, 函式的設計涉及到變進製數的概念, 數學的力量還是無比強大地...

4. 雙向廣度優先搜尋區分方向要用兩個open和closed, 相遇時刻拿出另乙個方向上狀態相同的節點比較麻煩, 需要考慮究竟用什麼當做鍵, 用什麼當做值, 把兩個方向上的搜尋**抽取到乙個方法中會使效能降低很多, 且需要拋異常來結束演算法,  不抽取則**又挺難看, 難辦. 雙向廣度優先搜尋路徑輸出是個麻煩事兒, 索性砍掉state類中記錄動作的屬性, 在輸出grid的時候現算更挺好, 方便且免轉化...

5. 程式設計上的細節, 什麼該預先算出, 用什麼方法實現節點擴充套件最爽, 怎麼實現demo最酷, 怎麼來考察執行效能, 這些都需要加強...

下面給出**...

普通廣度優先搜尋:

linkedlistopen = new linkedlist();

mapclosed = new hashmap();

state now;

listnodes;

public void search()

eightnum.showpath(now, null);

}

雙向廣度優先搜尋:

linkedlistopen1 = new linkedlist();

linkedlistopen2 = new linkedlist();

mapclosed1 = new hashmap();

mapclosed2 = new hashmap();

state now, s;

listnodes;

public void search() else if (!closed1.containskey(n.hashcode()))

open1.add(n);

} while (!now.equals(end1));

end1 = open1.peeklast();

} if (!open2.isempty()) else if (!closed2.containskey(n.hashcode()))

open2.add(n);

} while (!now.equals(end2));

end2 = open2.peeklast();

} }}

a*演算法:

priorityqueueopen = new priorityqueue(256,

new comparator()

});mapclosed = new hashmap();

state now;

listnodes;

public void search()

} eightnum.showpath(now, null);

}private int manhattan(byte bs)

這裡的open表要用優先順序佇列, 可是a*演算法框架要更新open表和closed表中的某些節點的f值, priorityqueue對遍歷的支援不太理想, 索性就去掉了更新值的部分, 每次直接插入算了. a*的啟發式函式要用曼哈頓距離, 那個"不在家"個數不太理想, 擴充套件的節點有時竟然比普通的廣度優先搜尋還多...

狀態空間元素的表示:

class state 

public state(byte g, state p, int g, int h)

public int hashcode()

public boolean equals(object o)

}

這個全排列的完美雜湊函式在效能上好像沒幫多大忙, 尤其用字串表示grid的時候, 可能是我不會用吧. 快取一下hash值, 貌似能快個幾十毫秒...

輔助資料, 計算與測試...

static final byte rules = ,,,

,,,,,};

static final char moves = ;

static final int facts = ;

static byte xys = new byte[8];

static state src, des;

static long count, timer;

public static listexpend(state now) else if (op == 3)

grid[8] = d;

nodes.add(new state(grid, now));

} count += nodes.size();

return nodes;

} public static void shuffle() while (!cansolve(g1, g2));

system.out.println("src");

showgrid(g1);

system.out.println("des");

showgrid(g2);

src = new state(g1, null);

des = new state(g2, null);

xys = getxys(g2);

}private static byte getrandom()

private static boolean cansolve(byte src, byte des)

public static byte getinvnums(byte grid)

return invs;

}public static byte getxys(byte bs)

public static void showpath(state now, state next)

system.out.format(" | %7d | %3d | %5d\n", count, path.size(),

system.currenttimemillis() - timer);

count = 0;

}private static void showgrid(byte grid)

system.out.println("-------");

system.out.format("%c %c %c\n", cs[0], cs[1], cs[2]);

system.out.format("%c %c %c\n", cs[3], cs[4], cs[5]);

system.out.format("%c %c %c\n", cs[6], cs[7], cs[8]);

system.out.println("-------");

}public static void main(string args)

/*隨機資料執行結果:

src des

------- -------

6 1 6 2

2 5 3 ---> 5 4 1

4 7 8 8 3 7

------- -------

相關統計:

-----------------------------

name | nodes | len | time

bfs | 155132 | 20 | 401

bibfs | 2562 | 20 | 10

astar | 646 | 20 | 0

-----------------------------

*/

ps: 演算法與api兩手抓, 兩手都要硬...

八數碼問題

八數碼問題 一.八數碼問題 八數碼問題也稱為九宮問題。在3 3的棋盤,擺有八個棋子,每個棋子上標有1至8的某一數字,不同棋子上標的數字不相同。棋盤上還有乙個空格,與空格相鄰的棋子可以移到空格中。要求解決的問題是 給出乙個初始狀態和乙個目標狀態,找出一種從初始轉變成目標狀態的移動棋子步數最少的移動步驟...

八數碼問題

2 6 4 1 3 7 0 5 8 8 1 5 7 3 6 4 0 2 樣例輸出 還有就是重判的問題,如何重判呢?第一種方法 把排列變成整數,然後只開乙個一維陣列,也就是說設計一套排列的編碼和解碼函式,把0 8的全排列和0 362879的整數意義一一對應起來。時間效率高,但編碼解碼法適用範圍並不大,...

八數碼問題

八數碼問題 題意 編號為1 8的8個正方形滑塊被擺成3行3列 有乙個格仔留空 如下圖所示 每次可以把與空格相鄰的滑塊 有公共邊才算相鄰 移到空格中,而他原來的位置 就成為了新的空格。如果無法到達目標局面,則輸出 1。2 6 4 13 75 8 移到後 8 1 5 73 642 樣例輸入 2 6 4 ...