日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

N-puzzle-Problem

發(fā)布時(shí)間:2023/12/8 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 N-puzzle-Problem 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?

N-Puzzle Problem

文章目錄

  • N-Puzzle Problem
    • Preview
      • N-Puzzle Problem:
      • N-Puzzle Problem 的可解性判斷
      • Algorithms
    • Three Stages and Related Algorithms
      • First phase:
        • 所需解決樣例以及最多時(shí)間:
        • Algorithm:A*
        • Code:
        • Result:
      • Second phase:
        • 所需解決樣例以及最多時(shí)間:
        • Algorithm:IDA*
        • Code:
        • Result:
      • Third phase:
        • 所需解決樣例以及最多時(shí)間:
        • Algorithm:IDA*+Disjoint Pattern Database Heuristics
        • 不斷優(yōu)化的啟發(fā)式
          • 1、曼哈頓距離
          • 2、Manhattan Distance+Linear Conflict
          • 3、非可加性的模式數(shù)據(jù)庫(kù)
          • 4、不相交的模式數(shù)據(jù)庫(kù)(可加性的)
          • 5、裁剪
          • 6、動(dòng)態(tài)分區(qū)模式數(shù)據(jù)庫(kù)啟發(fā)式 Dynamically-Partitioned Database Heuristics
        • Code:不相交模式數(shù)據(jù)庫(kù)靜態(tài)6-6-3分區(qū)
        • Result:
    • Reference resources

Preview

N-Puzzle Problem:

在人工智能中,常常以N-Puzzle 問題的求解為例子來說明各種搜索策略。

N=K*K-1;

當(dāng)N=8時(shí),即為重排九宮格問題;當(dāng)N=15時(shí),即為十五迷問題;

一個(gè)狀態(tài):N個(gè)數(shù)碼及一個(gè)空格的每一組置放形式,就形成了該問題的一個(gè)狀態(tài)。

N-Puzzle問題空間:所有(N+1)!個(gè)互不相同的狀態(tài)構(gòu)成了一個(gè)N-Puzzle問題空間。

128M 1e7

操作:平移操作——把與空格相鄰 的某一數(shù)碼移入空格,稱這種操作為平移操作。

Problem:對(duì)于給定的任一初始狀態(tài),使用平移操作,求解到目標(biāo)狀態(tài)的最優(yōu)步數(shù) (最少步驟的移法) 以及移動(dòng)的每一步狀態(tài)。

Goal position:

N-Puzzle Problem 的可解性判斷

分奇偶性然后根據(jù)逆序數(shù)判斷。

https://blog.csdn.net/Wood_Du/article/details/88730885

Algorithms

? N-Puzzle問題之所以能用來為例說明各種搜索策略,在于對(duì)于N-Puzzle問題,根據(jù)所需求解的初始狀態(tài)的復(fù)雜性,我們可以從爆搜開始,一步一步優(yōu)化,當(dāng)某種算法不足于求解時(shí),可從優(yōu)化數(shù)據(jù)結(jié)構(gòu),更換搜索算法上升一個(gè)境界,求得更加復(fù)雜的初始狀態(tài)的解。

:你會(huì)搜索嗎?

:我會(huì)爆搜 dfs+STL庫(kù),但是DFS不能找到最優(yōu)解;找最優(yōu)解我會(huì)bfs

:那么存狀態(tài)呢?

:STL庫(kù)會(huì)很廢效率,我可以用hash判重;正好學(xué)了Zobrist Hash

:你還有什么可以進(jìn)一步優(yōu)化嗎?

:為了減少狀態(tài)的膨脹,我可以使用雙向廣搜,從初始狀態(tài)和目標(biāo)狀態(tài)同時(shí)開始搜索,當(dāng)某方向遇到另一個(gè)方向搜索過的狀態(tài)的時(shí)候,則搜索成功。兩個(gè)方向?qū)拥玫阶詈蠼Y(jié)果。

:這些都是無信息搜索算法,你可以使用有信息搜索嗎?

:啟發(fā)式搜索,那就想辦法減少搜索范圍,降低問題復(fù)雜度。這個(gè)時(shí)候我們就可以上A*+Hash了。啟發(fā)函數(shù)可以用錯(cuò)位數(shù)或者曼哈頓距離。

:對(duì)于A*,需要每次找到Open表中f(f(n) = g(n)+h(n)) 最小的的元素。如果排序那么工作量會(huì)很大應(yīng)該怎么辦呢?

:上優(yōu)先隊(duì)列

:但是對(duì)于15碼問題,內(nèi)存不能存下狀態(tài)了

:IDA*,解決內(nèi)存問題。

是基于迭代加深的A*算法。并且不需要判重,不需要估價(jià)排序,用不到哈希表,空間需求量變得超級(jí)少。啟發(fā)函數(shù)用曼哈頓距離。在找最優(yōu)解的時(shí)候,對(duì)超過目前最優(yōu)解的地方進(jìn)行剪枝,可導(dǎo)致搜索深度急劇減少。再check一下不要回到上個(gè)狀態(tài)。

:一般的15碼樣例都能解決,但是對(duì)于15碼最復(fù)雜的一些樣例,仍然需要三四十分鐘才能解出答案。還有什么可以優(yōu)化嗎?

:那就只能去啃英文論文了。A.Felner,R.Korf的Disjoint Pattern Database Heuristics, 不相交模式數(shù)據(jù)庫(kù)啟發(fā)式算法。Additive Pattern Database Heuristics ——E.Korf,A.Felner,S.Hanan。這是一中新的設(shè)計(jì)更精確的可容許啟發(fā)式評(píng)價(jià)函數(shù)的方法,該方法基于模式數(shù)據(jù)庫(kù)。

本文我們將略去無信息搜索算法,求解最小步數(shù),詳解算法為:

從A* 開始,優(yōu)化數(shù)據(jù)結(jié)構(gòu);

再到IDA*;

最后用Pattern Database Heuristics解決15碼最復(fù)雜的樣例。

針對(duì)不同復(fù)雜度的樣例,本文后面將分為三個(gè)階段。

每個(gè)階段將說明解決的樣例,求解的要求時(shí)間,算法以及啟發(fā)函數(shù),代碼實(shí)現(xiàn)以及每個(gè)樣例的解決時(shí)間。

對(duì)于展示代碼因?yàn)榇a量很大,并且是一個(gè)框架,所以只能展示核心代碼,若需要查看整個(gè)項(xiàng)目代碼,我會(huì)push到github上。

Three Stages and Related Algorithms

First phase:

所需解決樣例以及最多時(shí)間:

? 對(duì)于以下兩個(gè)實(shí)例,均能夠在1秒之類解出

Algorithm:A*

? A*算法是一種靜態(tài)網(wǎng)中求解最短路徑最有效的直接搜索方法也是也是一種啟發(fā)式算法。在搜索過程中使用啟發(fā)函數(shù)。估價(jià)函數(shù)與實(shí)際值越接近,最終搜索到目標(biāo)格局的時(shí)間越快。

估價(jià)函數(shù)表示:

f(n) = g(n) + h(n) //f(n) 表示從初始狀態(tài)到目標(biāo)狀態(tài)的估測(cè)代價(jià) //g(n) 表示從初始狀態(tài)到當(dāng)前狀態(tài)(節(jié)點(diǎn)n)的代價(jià)(已經(jīng)確定) //h(n) 表示從當(dāng)前狀態(tài)(節(jié)點(diǎn)n)到目標(biāo)狀態(tài)的估測(cè)代價(jià)(預(yù)測(cè))h(n) < h'(n) //h'(n)為當(dāng)前狀態(tài)到目標(biāo)狀態(tài)的實(shí)際步數(shù)

h(n) 的好壞直接影響評(píng)估函數(shù)的好壞。

流程圖:

? 從初始狀態(tài)出發(fā) =>經(jīng)過一系列中間狀態(tài) =>最終到達(dá)目標(biāo)狀態(tài)(或者無法到達(dá))。

? 該算法用于經(jīng)過中間狀態(tài)時(shí)候的行進(jìn)策略(其中的中間狀態(tài)或者由題目給出,或者在前邊已經(jīng)推導(dǎo)得出)。

優(yōu)點(diǎn):與廣度優(yōu)先搜索策略和深度優(yōu)先搜索策略相比,A*算法不是盲目搜索,而是有提示的搜索

缺點(diǎn):該算法一般要使用大量的空間用于存儲(chǔ)已搜索過的中間狀態(tài),防止重復(fù)搜索。隨著樣例變復(fù)雜將會(huì)爆內(nèi)存。

Code:

完整代碼傳送門:???

Search為A*算法,此代碼由于調(diào)用了框架中其他類的代碼所以比較抽象,我是邊百度java邊寫這個(gè)項(xiàng)目,沒學(xué)過java的娃娃面向百度編程。所以如果你會(huì)java,相信你噸噸噸就看明白我代碼了。

package core.astar;import core.problem.Action; import core.problem.Problem; //操作 import core.problem.State;import java.util.ArrayList;public class AStar {public AStar(Problem problem) {super();this.problem = problem;}public Node childNode(Node parent, Action action) {State state = problem.result(parent.getState(), action);//getPathCost 初始到當(dāng)前的實(shí)際代價(jià) stepCost 從父級(jí)到后續(xù)任務(wù)的路徑成本int pathCost = parent.getPathCost() + problem.stepCost(parent.getState(), action);int heuristic = problem.heuristic(state); //估計(jì)從狀態(tài)到目標(biāo)狀態(tài)最便宜路徑的成本return new Node(state, parent, action, pathCost, heuristic);}public Problem getProblem() {return problem;}public void setProblem(Problem problem) {this.problem = problem;}public Node Search(){//起始節(jié)點(diǎn)State initState = problem.getInitialState();Node node = new Node(initState, null, null, 0, problem.heuristic(initState));Fringe fringe = new Fringe();fringe.insert(node);Explored explored = new Explored();while (true) {if (fringe.isEmpty()) return null; //失敗node = fringe.pop(); //choose the lowest-cost node in frontierif (problem.goalTest(node.getState())) return node;explored.insert(node.getState());for (Action action : problem.Actions(node.getState())) {Node child = childNode(node, action);//child.getState()不再在擴(kuò)展節(jié)點(diǎn)的集合(Close表中)且fringe(Open表)中不存在狀態(tài)為state的節(jié)點(diǎn) 則將節(jié)點(diǎn)插入fringe中if (!explored.contains(child.getState()) && !fringe.contains(child.getState())) {fringe.insert(child);}else {/**如果鄰接結(jié)點(diǎn)N’在CLOSED表中,比較CLOSED表中的g(N')值和當(dāng)前的g(N')值,如果當(dāng)前的g(N')更小,那么刪除CLOSED表中的N',把N設(shè)成N'的父節(jié)點(diǎn),重新將N'插入OPEN表。如果鄰接結(jié)點(diǎn)N’在OPEN表中,比較OPEN表中的g(N')值和當(dāng)前的g(N')值,如果當(dāng)前的g(N')更小,那么刪除OPEN表中的N',把N設(shè)成N'的父節(jié)點(diǎn),重新將N'插入OPEN表。***/Node revisited = fringe.revisited(child.getState());if (revisited != null && revisited.evaluation() > child.evaluation()) {fringe.replace(revisited, child);//用child節(jié)點(diǎn)代替Fringe中的 revisited節(jié)點(diǎn)}}}} }//用動(dòng)畫展示問題的解路徑public void solution(Node node){// Fix me// 調(diào)用Problem的drawWorld方法,和simulateResult方法problem.drawWorld();}private Problem problem; }

Result:

項(xiàng)目目錄:Searching_Student: E:\University\AI\Searching_student

NoInitial StateStepsTimeLimited Time
18, 6, 7, 2, 5, 4, 3, 0, 1310.132s1s
26, 4, 7, 8, 5, 0, 3, 2, 1310.133s1s
38, 13, 0, 6, 1, 15, 9, 14, 3, 4, 5, 11, 7, 2, 10, 12521.929s
42,9,5,11, 8,3,4,14, 7,10,1,12, 0,15,6,13GC
54,7,0,9,12,10,11,8,14,6,15,1,2,5,3,13GC

Second phase:

所需解決樣例以及最多時(shí)間:

4階的,能夠在與老師程序同級(jí)別的時(shí)間內(nèi),解決相同 的問題實(shí)例。

對(duì)于以上后面幾個(gè)初始狀態(tài),A*就已經(jīng)無法解決。因?yàn)闀?huì)生成太多新狀態(tài)并消耗大量?jī)?nèi)存維護(hù)這些列表。直接爆內(nèi)存。

Algorithm:IDA*

IDA*算法, ID(Iterative Deepening)指的是迭代加深.

迭代加深搜索算法,在搜索過程中采用估值函數(shù),以減少不必要的搜索。

IDA*算法核心:

? 設(shè)置每次可達(dá)的最大深度depth,若沒有到達(dá)目標(biāo)狀態(tài)則加深最大深度。

? 采用估值函數(shù),剪掉f(n)大于depth的路徑

IDA*算法的步驟

a、首先對(duì)初始狀態(tài)進(jìn)行評(píng)估, 評(píng)估值作為最小限度, 而最大限度為自己的設(shè)置.這個(gè)評(píng)估值在這個(gè)問題中可以用此狀態(tài)到正確狀態(tài)的每個(gè)位置的曼哈頓距離來表示.

b、從最小限度到最大限度進(jìn)行遍歷, 此值作為當(dāng)前dfs的限度值, 這個(gè)限度不斷在有效范圍內(nèi)遞增的過程就稱作迭代加深

c、進(jìn)行dfs, 調(diào)整狀態(tài), 將新狀態(tài)加入到新的dfs中, 直到找到了一個(gè)解(由于迭代加深, 此解為最優(yōu)解). 進(jìn)行回溯, 加入路徑, 算法結(jié)束.

IDA* is described as follows:

  • Set threshold equal to the heuristic evaluation of the initial state.

  • Conduct a depth-first search, pruning a branch when the cost of the latest node exceeds threshold. If a solution is found during the search, return it.

  • If no solution is found during the current iteration, increment threshold by the minimum amount it was exceeded, and go back to the previous step.

  • 設(shè)置閾值等于初始狀態(tài)的啟發(fā)式評(píng)估。

  • 進(jìn)行深度優(yōu)先搜索,在最新節(jié)點(diǎn)的成本超過閾值時(shí)修剪分支。如果在搜索過程中找到解決方案,請(qǐng)將其返回。

  • 如果在當(dāng)前迭代期間未找到解決方案,則將閾值增加超過最小值,然后返回上一步驟。

Code:

完整代碼傳送門:???

IDA*代碼除了讀取數(shù)據(jù)時(shí)調(diào)用了框架中的類,其他在一個(gè)類完成。

當(dāng)時(shí)已經(jīng)對(duì)框架有點(diǎn)絕望。由于我使用反向搜索使用框架會(huì)改很多類。加上不能與滑塊公用一個(gè)算法,所以寫在一個(gè)類里面。

第二階段我采用IDA*反向搜索,從目標(biāo)狀態(tài)到初始狀態(tài)搜索,所以看代碼要注意。速度會(huì)快很多,對(duì)于給定樣例有的比老師快幾十倍,分析過原因。不過后面理論又被自己否定,應(yīng)該是由于樣例的特殊性所以加快了速度。

main函數(shù)中調(diào)用:

ArrayList<Problem> problems = ProblemFactory.getProblems(1);test2(problems);

test2():

public static void test2(ArrayList<Problem> problems) {for (Problem problem : problems) {Rstep=0;flg=0;result = new int[200][20];PuzzleState state = (PuzzleState) problem.getInitialState();side = state.getSide();tmp = state.getStatus();System.out.println();xx = new int[20];yy = new int[20];for (int i = 0; i < side * side; i++) {if (tmp[i] == 0) pos = i;else {xx[tmp[i]] = (i / side);yy[tmp[i]] = (i % side);}}if (!check(tmp)) System.out.println("No");mat = new int[20];for (int i = 0; i < side * side; i++) mat[i] = i + 1;mat[side * side - 1] = 0;pos = side * side - 1;double time1 = 0;Stopwatch timer1 = new Stopwatch(); // for(int i=0;i<100;i++){ // layer[i]=-1; // }//System.out.println(H(mat));for (bound = H(mat); bound <= 100; bound = dfs(0, H(mat), 4))if (flg == 1) break;time1 = timer1.elapsedTime();Ans_show();System.out.printf("行走了 %s 步,執(zhí)行了 %.3f 秒\n", Rstep, time1);}}

check()方法:檢查是否可行解

public static boolean check(int[] a) {int tot=0;int flag=0;for(int i=0;i<side*side;i++){if(a[i]==0) {flag = i/side;continue;}for(int j=0;j<i;j++){if(a[j]>a[i]){tot++;}}}if(side%2==1) return tot%2==0;else{tot+= abs(flag-(side-1));if(tot%2==0) return true;else return false;}}

H()方法:算曼哈頓距離

public static int H(int[] mat) {int h = 0;for (int i = 0; i < side*side-1; i++) {h += abs(xx[mat[i]] - (i / side)) + abs(yy[mat[i]] - (i % side));}return h;}

ok()方法:判斷是否回到上一個(gè)狀態(tài)

public static boolean ok(int x,int y){if(x>y){int ff=x;x=y;y=ff;}if(x==0&y==1) return false; //與操作 1 1 為1if(x==2&&y==3) return false;return true;}

IDA*:

public static int dfs(int step, int h, int las) {//g(n)+h(n)=f(n) 更新f(n) bound 最大限度 采用估值函數(shù),剪掉f(n)大于depth的路徑if (step + h > bound) return step + h; // // if(layer[h]==-1)layer[h]=step; // if(step>layer[h]+15){ // System.out.printf("enter\n"); // return step+h; // }if (h == 0) { // 到達(dá)最終狀態(tài) 輸出g(n)即可// System.out.println(step);flg = 1;Rstep = step;return step;}int pos1 = pos;int ret = 127, x = pos1 / side, y = pos1 % side;int dx, dy, tar, ht, temp, i;for (i = 0; i < 4; i++) { //四個(gè)方向擴(kuò)展dx = x + u[i];dy = y + p[i];if (dx < 0 || dy < 0 || dx > side - 1 || dy > side - 1 || !ok(i, las)) continue;tar = (dx * side) + dy; //計(jì)算出擴(kuò)展出的新節(jié)點(diǎn)的一維坐標(biāo) 2,2 2*4+2= 10mat[pos1] = mat[tar]; // 0的坐標(biāo)等于擴(kuò)展出來的點(diǎn)的坐標(biāo) a.mat[10]=11;mat[tar] = 0;//相當(dāng)于swap()pos = tar;//計(jì)算新的h值//階段三主要在這修改 用不相交模式數(shù)據(jù)庫(kù) h(n) 為當(dāng)前節(jié)點(diǎn)的各點(diǎn)的曼哈頓距離和。ht = h - (Math.abs(xx[mat[pos1]] - dx) + Math.abs(yy[mat[pos1]] - dy)) + Math.abs(xx[mat[pos1]] - x) + Math.abs(yy[mat[pos1]] - y);if (step + ht <= bound)for (int k = 0; k < side*side; k++)result[step][k] = mat[k];temp = dfs(step + 1, ht, i);if (flg == 1) return temp;if (ret > temp) ret = temp;mat[tar] = mat[pos1];mat[pos1] = 0;pos = pos1;}return ret;}

Result:

項(xiàng)目目錄:SearchingAstar: E:\University\AI\SearchingAstar
Limited Time為老師IDA跑的時(shí)間。從結(jié)果可以看出,反向IDA速度會(huì)更快。

NoInitial StateStepsTimeLimited Time
18, 6, 7, 2, 5, 4, 3, 0, 1310.000s0.047s
26, 4, 7, 8, 5, 0, 3, 2, 1310.003s0.047s
38, 13, 0, 6, 1, 15, 9, 14, 3, 4, 5, 11, 7, 2, 10, 12520.147s0.304s
42,9,5,11, 8,3,4,14, 7,10,1,12, 0,15,6,13512.423s3.652s
54,7,0,9,12,10,11,8,14,6,15,1,2,5,3,13560.554s12.367s
612, 10, 3, 2, 0, 7, 14, 9, 1, 15, 5, 6, 8, 4, 13, 11574.341s75.458s
712, 1, 5, 6, 2, 11, 7, 9, 14, 10, 0, 4, 15, 3, 13, 8500.058s3.671s
84, 6, 15, 13, 12, 9, 10, 2, 8, 0, 7, 3, 14, 5, 1, 116110.918s299.286s
915, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 1, 2, 0701761.019s

Third phase:

所需解決樣例以及最多時(shí)間:

? 4階的,能夠在1分鐘之內(nèi),解出以下實(shí)例

說明:對(duì)于這個(gè)樣例,曾聽說過老師用IDA*大概跑了四十多分鐘得出結(jié)果,不過由于樣例的特殊性,我們可以使用反向搜索,這樣會(huì)增快速度,我跑的時(shí)間不到30分鐘,不過這個(gè)時(shí)間肯定也不是我們所能接受的,我們需要的是在一分鐘內(nèi)

對(duì)于15碼最復(fù)雜的狀態(tài),A*肯定不能解,會(huì)爆內(nèi)存。

IDA*雖然在空間上消耗少,但是由于初始狀態(tài)逆序數(shù)大,要搜很久,即大概三四十分鐘才能解決。

解決辦法:

a、曼哈頓距離加線性沖突——優(yōu)化不了多少

b、添加不相交模式數(shù)據(jù)庫(kù)(Disjoint Pattern Database Heuristics)與靜態(tài)6-6-3分區(qū)

Algorithm:IDA*+Disjoint Pattern Database Heuristics

這個(gè)算法就只能硬著頭皮去讀E.Korf和A.Felner的論文Disjoint Pattern Database Heuristics。

就剛開始看了Tsan-sheng Hsu的一個(gè)應(yīng)該是用來講課的pdf,看完之后???開始思考三連:我是,我去,我思???大概花了一下午的時(shí)間看完那篇pdf,當(dāng)時(shí)是很崩潰的,伴隨著這門課的無理取鬧與老師的嗯。。。就已經(jīng)絕望了,此時(shí),滑塊那邊也沒有進(jìn)展,老師張口閉口嚴(yán)格證明就很無語老師你是真的沒搞懂滑塊吧,真準(zhǔn)備棄了。當(dāng)天晚上又因?yàn)橐粋€(gè)評(píng)估函數(shù)的優(yōu)劣性被同學(xué)懟了,心情很糟糕。

第二天醒來已經(jīng)中午,開始接手了N-Puzzle和滑塊兩個(gè)問題,開始了找牛逼網(wǎng)友過程。也找到了那篇論文開始啃,(英語真的毀我一生)。

參考論文:

Additive Pattern Database Heuristics ——E.Korf,A.Felner,S.Hanan

Disjoint Pattern Database Heuristics——E.Korf,A.Felner

以下內(nèi)容來自論文(有些地方翻譯會(huì)有問題)

不斷優(yōu)化的啟發(fā)式

1、曼哈頓距離

? 例如,在滑動(dòng)拼圖拼圖中,要將拼貼從位置x移動(dòng)到位置y,x和y必須相鄰,并且位置y必須為空。如果我們忽略空約束,我們得到一個(gè)簡(jiǎn)化的問題,任何瓦片都可以移動(dòng)到任何相鄰位置,并且多個(gè)瓦片可以占據(jù)相同的位置。在這個(gè)新問題中,瓦片彼此獨(dú)立,我們可以通過沿著最短路徑將每個(gè)瓦片移動(dòng)到其目標(biāo)位置來最佳地解決任何實(shí)例,計(jì)算所做的移動(dòng)的數(shù)量。

? 解決這個(gè)簡(jiǎn)化問題的最佳解決方案的成本恰好是曼哈頓從初始狀態(tài)到目標(biāo)狀態(tài)的距離。由于我們刪除了對(duì)移動(dòng)的約束,原始問題的任何解決方案也是簡(jiǎn)化問題的解決方案,并且針對(duì)簡(jiǎn)化問題的最優(yōu)解決方案的成本是對(duì)原始問題的最優(yōu)解決方案的成本的下限。

不足:曼哈頓距離之所以只是實(shí)際解決方案成本的下限,就是沒有考慮到滑塊的相互作用。

可改進(jìn):

通過考慮其中一些相互作用,我們可以計(jì)算出更準(zhǔn)確的可接受的啟發(fā)函數(shù)。

2、Manhattan Distance+Linear Conflict

Historically, the linear-con?ict heuristic was the ?rst signi?cant improvementover Manhattan distance [5]. It applies to tiles in their goal row or column, but reversed relative to each other. For example, assume the top row of a given state contains the tiles (2 1) in that order, but in the goal state they appear in the order (1 2). To reverse them, one of the tiles must move out of the top row, to allow the other tile to pass by, and then move back into the top row. Since these two moves are not counted in the Manhattan distance of either tile, two moves can be added to the sum of the Manhattan distances of these two tiles without violating admissibility.

(從歷史上看,線性沖突啟發(fā)式是曼哈頓距離的第一個(gè)顯著改進(jìn)[5]。它適用于目標(biāo)行或列中的切片,但相對(duì)于彼此反轉(zhuǎn)。例如,假設(shè)給定狀態(tài)的頂行按順序包含tile(2 1),但在目標(biāo)狀態(tài)下它們按順序出現(xiàn)(1 2)。要反轉(zhuǎn)它們,其中一個(gè)切片必須移出頂行,以允許另一個(gè)切片通過,然后移回頂行。由于這兩個(gè)移動(dòng)不計(jì)入任一區(qū)塊的曼哈頓距離,因此可以將兩個(gè)移動(dòng)添加到這兩個(gè)區(qū)塊的曼哈頓距離的總和而不違反可接受性。)

同樣的想法也可以應(yīng)用于其目標(biāo)列中的切片。實(shí)際上,目標(biāo)位置的圖塊可以同時(shí)參與行和列的沖突。由于解決行沖突所需的額外移動(dòng)是垂直移動(dòng),而解決列沖突所需的額外移動(dòng)是水平移動(dòng),因此兩組移動(dòng)都可以添加到曼哈頓距離,而不會(huì)違反允許性。與曼哈頓距離相比,線性沖突啟發(fā)式減少了一個(gè)數(shù)量級(jí)的節(jié)點(diǎn)數(shù)量,成本幾乎是速度的兩倍,總體加速比超過五倍。接下來的兩行用于不相交的模式數(shù)據(jù)庫(kù)啟發(fā)式。

3、非可加性的模式數(shù)據(jù)庫(kù)

圖顯示了十五個(gè)拼圖拼貼的子集,稱為邊緣拼貼。對(duì)于給定狀態(tài),使邊緣拼貼到其目標(biāo)位置所需的最小移動(dòng)次數(shù)(包括其他拼塊的所需移動(dòng))是解決整個(gè)拼圖所需的移動(dòng)次數(shù)的下限。

與其他瓦片的位置無關(guān)。

因此,我們可以預(yù)先計(jì)算所有這些值,將它們存儲(chǔ)在內(nèi)存中,并在搜索過程中查找它們。由于有七個(gè)邊緣拼貼和一個(gè)空白,以及十六個(gè)不同的位置,邊緣拼貼和空白的可能排列總數(shù)為16!/(16-8)!= 518,918,400。

對(duì)于每個(gè)排列,我們存儲(chǔ)將數(shù)字圖塊和空白移動(dòng)到其目標(biāo)位置所需的移動(dòng)次數(shù),這需要不到一個(gè)字節(jié)。因此,我們可以將整個(gè)模式數(shù)據(jù)庫(kù)表存儲(chǔ)在少于495兆字節(jié)的內(nèi)存中。

存儲(chǔ)表后,我們使用IDA *搜索特定問題實(shí)例的最佳解決方案。在生成每個(gè)狀態(tài)時(shí),使用數(shù)字圖塊和空白的位置來計(jì)算圖案數(shù)據(jù)庫(kù)中的索引,并且使用相應(yīng)的條目,即解決數(shù)字圖塊和空白所需的移動(dòng)的數(shù)量,作為該狀態(tài)的啟發(fā)式值。

使用這種模式數(shù)據(jù)庫(kù),Culberson和Schaeffer將生成的節(jié)點(diǎn)數(shù)量減少了346倍,并將運(yùn)行時(shí)間縮短了6倍,與曼哈頓距離相比[1]。將此與另一個(gè)模式數(shù)據(jù)庫(kù)相結(jié)合,并將兩個(gè)數(shù)據(jù)庫(kù)值的最大值作為整體啟發(fā)式值,將生成的節(jié)點(diǎn)減少大約一千,將運(yùn)行時(shí)間減少十二。

局限:

非加性模式數(shù)據(jù)庫(kù)的主要限制是它們無法解決更大的問題。例如,由于二十四個(gè)拼圖包含25個(gè)不同的位置,一個(gè)覆蓋n個(gè)拼貼和空白的模式數(shù)據(jù)庫(kù)需要25!/(25 - n - 1)!條目。僅有六個(gè)圖塊和空白的數(shù)據(jù)庫(kù)將需要超過24億個(gè)條目。此外,來自僅六個(gè)瓦片的數(shù)據(jù)庫(kù)的值將小于所有瓦片的曼哈頓距離。對(duì)于多個(gè)數(shù)據(jù)庫(kù),允許組合它們的最佳方法是獲取其值的最大值,即使這些圖塊組是不相交的。原因是非加性模式數(shù)據(jù)庫(kù)值包括解決模式切片所需的所有移動(dòng),包括其他切片的移動(dòng)

可改進(jìn):

我們希望能夠在不違反可接受性的情況下對(duì)其值進(jìn)行求和,以獲得更準(zhǔn)確的啟發(fā)式,而不是采用最大的不同模式數(shù)據(jù)庫(kù)值。這是不相交模式數(shù)據(jù)庫(kù)的主要思想。

4、不相交的模式數(shù)據(jù)庫(kù)(可加性的)

為了構(gòu)建滑動(dòng)拼圖的不相交模式數(shù)據(jù)庫(kù),我們將拼貼劃分為不相交的組,這樣任何拼貼都不屬于多個(gè)組。然后,我們預(yù)先計(jì)算每組中瓦片最小移動(dòng)次數(shù)的表格,這些移動(dòng)是將這些瓦片移動(dòng)到其目標(biāo)位置所需的。我們稱這些表為一組,每組一個(gè)瓦片,一個(gè)不相交的模式數(shù)據(jù)庫(kù),或簡(jiǎn)稱為adisjoint數(shù)據(jù)庫(kù)。然后,給定搜索中的特定狀態(tài),對(duì)于每組圖塊,我們使用這些圖塊的位置來計(jì)算相應(yīng)表格中的索引,檢索解決該組中圖塊所需的移動(dòng)次數(shù),然后將每個(gè)組的值相加,以計(jì)算給定狀態(tài)的整體啟發(fā)式。該值至少與曼哈頓距離一樣大,并且通常更大,因?yàn)樗紤]了同一組中的切片之間的交互。

上述不相交數(shù)據(jù)庫(kù)和非附加數(shù)據(jù)庫(kù)之間的關(guān)鍵區(qū)別在于,非加法數(shù)據(jù)庫(kù)包括解決圖案圖塊所需的所有移動(dòng),包括不在圖案集中的圖塊移動(dòng)。結(jié)果,給定兩個(gè)這樣的數(shù)據(jù)庫(kù),即使它們的區(qū)塊之間沒有重疊,我們也只能將這兩個(gè)值中的最大值作為可接受的啟發(fā)式,因?yàn)樵谝粋€(gè)數(shù)據(jù)庫(kù)中計(jì)數(shù)的移動(dòng)可能會(huì)移動(dòng)另一個(gè)數(shù)據(jù)庫(kù)中的區(qū)塊,因此這些舉動(dòng)將被計(jì)算兩次。在不相交的數(shù)據(jù)庫(kù)中,我們只計(jì)算組中切片的移動(dòng)。

這兩種類型的數(shù)據(jù)庫(kù)之間的第二個(gè)區(qū)別是我們的不相交數(shù)據(jù)庫(kù)不考慮空白位置,減小它們的大小。一個(gè)不相交的數(shù)據(jù)庫(kù)包含了解決一組圖塊所需的最小移動(dòng)量,對(duì)于所有可能的空白位置。

該搜索的狀態(tài)由所討論的圖塊的位置和空白的位置唯一地確定,并且僅計(jì)算感興趣的圖塊的移動(dòng)。由于滑動(dòng)拼圖拼圖的操作員是可逆的,我們可以從其目標(biāo)位置開始對(duì)每個(gè)拼貼執(zhí)行單個(gè)搜索,并記錄將拼塊移動(dòng)到每個(gè)其他位置需要多少移動(dòng)。對(duì)所有圖塊執(zhí)行此操作會(huì)生成一組表格,這些表格為每個(gè)圖塊的每個(gè)可能位置提供距其目標(biāo)位置的曼哈頓距離。

對(duì)于每個(gè)圖塊,我們可以使用上述廣度搜索來自動(dòng)計(jì)算將圖塊從任何位置移動(dòng)到其目標(biāo)位置所需的最小移動(dòng)次數(shù)的表格。這樣的一組表格將包含從每個(gè)位置到其目標(biāo)位置的每個(gè)瓦片的曼哈頓距離。然后,給定一個(gè)特定的狀態(tài),我們只需在相應(yīng)的表中查找每個(gè)圖塊的位置并對(duì)結(jié)果值求和,從而計(jì)算曼哈頓距離的總和

因此我們可以將曼哈頓距離相加以獲得可接受的啟發(fā)式

作為一般規(guī)則,在對(duì)圖塊進(jìn)行分區(qū)時(shí),我們希望將目標(biāo)狀態(tài)中彼此靠近的圖塊組合在一起,因?yàn)檫@些圖塊將彼此交互最多。

使用[12]中開發(fā)的分析結(jié)果,我們可以預(yù)測(cè),單獨(dú)使用曼哈頓距離解決二十四難題每個(gè)問題平均需要大約5萬年!對(duì)于10,000個(gè)初始狀態(tài)的隨機(jī)樣本,曼哈頓平均距離是76.078個(gè)移動(dòng),而對(duì)于我們的不相交數(shù)據(jù)庫(kù)啟發(fā)式,它是81.607個(gè)移動(dòng)

第一行給出了曼哈頓距離啟發(fā)式的結(jié)果。

第二行是通過線性沖突增強(qiáng)的曼哈頓距離。

第三行表示啟發(fā)式,它是圖4左側(cè)所示的七和八數(shù)據(jù)庫(kù)值的總和

第四行表示通過從第三行的啟發(fā)式開始計(jì)算的啟發(fā)式。然后,我們計(jì)算圖4右側(cè)所示的七和八數(shù)據(jù)庫(kù)值的總和。最后,整體啟發(fā)式是這兩個(gè)總和中的最大值

第一個(gè)數(shù)據(jù)列顯示了啟發(fā)函數(shù)在1000個(gè)初始狀態(tài)下的平均值。第二列給出了每個(gè)問題實(shí)例生成的平均節(jié)點(diǎn)數(shù),以找到第一個(gè)最優(yōu)解。第三列顯示算法的平均速度,以每秒節(jié)點(diǎn)數(shù)為單位,, on a 440 MegaHertz Sun Ultra10 workstation. 。第四列表示找到第一個(gè)最佳解決方案的平均運(yùn)行時(shí)間(以秒為單位)。最后一列給出了生成的平均節(jié)點(diǎn)數(shù),以找到問題實(shí)例的所有最優(yōu)解。

采用其最大值來組合來自不同模式數(shù)據(jù)庫(kù)的啟發(fā)式算法。這是最通用的方法,因?yàn)槿魏蝺蓚€(gè)可接受的啟發(fā)式方法的最大值始終是另一個(gè)可接受的啟發(fā)式方法。我們引入了不相交模式數(shù)據(jù)庫(kù),以允許將來自不同數(shù)據(jù)庫(kù)的值相加,從而產(chǎn)生更準(zhǔn)確的啟發(fā)式值。不相交的模式數(shù)據(jù)庫(kù)將子目標(biāo)集劃分為不相交的組,然后將解決每個(gè)組中所有子目標(biāo)的成本加在一起。這要求組不相交,并且單個(gè)運(yùn)算符僅影響單個(gè)組中的子目標(biāo)。例如,在滑動(dòng)拼圖游戲中,每個(gè)操作員僅移動(dòng)一個(gè)拼貼。這與獲取不同值的最大值一樣有效,但更準(zhǔn)確,并且仍然可以接受。

5、裁剪

used a technique, based on ?nite-state machines (FSMs), to prune duplicate nodes representing the same state arrived at via different paths in the graph

*使用了一種基于有限狀態(tài)機(jī)(FSM)的技術(shù)來修剪表示通過圖中不同路徑到達(dá)的相同狀態(tài)的重復(fù)節(jié)點(diǎn)[16]。 FSM修剪減少了IDA 在五個(gè)問題上產(chǎn)生的節(jié)點(diǎn)數(shù)量,范圍從2.4到3.6。對(duì)于這項(xiàng)工作,我們沒有使用FSM修剪,因?yàn)樵摷夹g(shù)很復(fù)雜,結(jié)果取決于所使用的特定FSM,使得其他研究人員難以重現(xiàn)相同的結(jié)果。

6、動(dòng)態(tài)分區(qū)模式數(shù)據(jù)庫(kù)啟發(fā)式 Dynamically-Partitioned Database Heuristics

? 之前(Korf&Felner,2002)我們展示了如何將滑動(dòng)拼圖塊靜態(tài)劃分為不相交的拼貼組以計(jì)算可接受的啟發(fā)式,為每個(gè)狀態(tài)和問題實(shí)例使用相同的分區(qū)。在這里,我們擴(kuò)展該方法并顯示它也適用于其他域。我們還提出了另一種加法啟發(fā)式方法,我們將其稱為動(dòng)態(tài)分區(qū)模式數(shù)據(jù)庫(kù)。在這里,我們動(dòng)態(tài)地將問題劃分為每個(gè)搜索狀態(tài)的不相交的子問題

論文:Additive Pattern Database Heuristics

15-puzzle ;24-puzzle 動(dòng)態(tài)模式數(shù)據(jù)庫(kù)會(huì)比靜態(tài)模式數(shù)據(jù)庫(kù)慢。

35-puzzle 動(dòng)態(tài)模式數(shù)據(jù)庫(kù)會(huì)比靜態(tài)模式數(shù)據(jù)庫(kù)快。

Code:不相交模式數(shù)據(jù)庫(kù)靜態(tài)6-6-3分區(qū)

完整代碼傳送門:???

模式數(shù)據(jù)庫(kù)生成器:

/*** File: PatternDatabaseGenerator.java* Author: Brian Borowski* Date created: June 10, 2010* Date last modified: May 13, 2011*/ import java.io.BufferedOutputStream; import java.io.DataOutputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Queue; import java.util.Set; import java.util.StringTokenizer;/*** Examples:* When generating a complete pattern database (i.e. no dummy tiles):* java PatternDatabaseGenerator 8 1,2,3,4,5,6,7,8,0 8-puzzle.db** When generating a disjoint additive pattern database (i.e. dummy tiles 'x'):* java PatternDatabaseGenerator 15 0,2,3,4,x,x,x,x,x,x,x,x,x,x,x,0 15-puzzle-663-0.db* java PatternDatabaseGenerator 15 1,x,x,x,5,6,x,x,9,10,x,x,13,x,x,0 15-puzzle-663-1.db* java PatternDatabaseGenerator 15 x,x,x,x,x,x,7,8,x,x,11,12,x,14,15,0 15-puzzle-663-2.db*/ public final class PatternDatabaseGenerator {public static final byte KEY_NOT_FOUND = -1;final int numOfTiles, numOfTilesMinusOne, dimension;PrimitiveHashMap tempMap;List<Entry> stateToCostEntries_8_puzzle;byte[] costTable_15_puzzle;long[] configTable_15_puzzle;public PatternDatabaseGenerator(final int numOfTiles, final long boardConfig,final byte dummyTile, final String filename) {this.numOfTiles = Node.numOfTiles = numOfTiles;this.numOfTilesMinusOne = numOfTiles - 1;this.dimension = Node.dimension = (int)Math.sqrt(numOfTiles);DataOutputStream dos = null;if (filename != null) {try {dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(filename)));} catch (final FileNotFoundException fnfe) {System.err.println("Error: Cannot open file '" + filename + "' for output.");System.exit(1);}}if (numOfTilesMinusOne == 15) {generateFifteenPuzzleDB(dummyTile, boardConfig);outputFifteenPuzzleData(filename, dos);} else {generateEightPuzzleDB(boardConfig);outputEightPuzzleData(filename, dos);}}private void generateFifteenPuzzleDB(final byte dummyTile,final long boardConfig) {final boolean[] tilesInSubset = computeSubset(dummyTile, boardConfig);final int[] tilePositions = new int[tilesInSubset.length];int numTilesInSubset = 0;for (int i = 0; i < tilePositions.length; ++i) {if (tilesInSubset[i]) {tilePositions[i] = numTilesInSubset++;}}breadthFirstSearch(boardConfig, tilesInSubset);final int tableLength = (int)Math.pow(2, numTilesInSubset * 4);costTable_15_puzzle = new byte[tableLength];configTable_15_puzzle = new long[tableLength];for (int i = tableLength - 1; i >= 0; --i) {costTable_15_puzzle[i] = KEY_NOT_FOUND;}System.err.println("Total states visited: " + tempMap.size());System.err.print("Removing duplicates...");final Set<Entry> entries = tempMap.entrySet();final Iterator<Entry> it = entries.iterator();while (it.hasNext()) {final Entry entry = it.next();final long config = entry.getKey();final byte movesRequired = entry.getValue();final int index = indexFor(config, true, tilesInSubset, tilePositions);final byte moves = costTable_15_puzzle[index];if (moves == KEY_NOT_FOUND || movesRequired < moves) {configTable_15_puzzle[index] = config;costTable_15_puzzle[index] = movesRequired;}}int numElements = 0;for (int i = tableLength - 1; i >= 0; --i) {if (costTable_15_puzzle[i] != KEY_NOT_FOUND) {++numElements;}}System.err.println("done");System.err.println("States in subset: " + numElements);}private void generateEightPuzzleDB(final long boardConfig) {breadthFirstSearch(boardConfig, null);final PrimitiveHashMap costMap_8_puzzle = new PrimitiveHashMap();System.err.println("Total states visited: " + tempMap.size());System.err.print("Removing duplicates...");final Set<Entry> entries = tempMap.entrySet();final Iterator<Entry> it = entries.iterator();while (it.hasNext()) {final Entry entry = it.next();final long config = entry.getKey();final byte movesRequired = entry.getValue();final byte moves = costMap_8_puzzle.get(config);if (moves == PrimitiveHashMap.KEY_NOT_FOUND || movesRequired < moves) {costMap_8_puzzle.put(config, movesRequired);}it.remove();}System.err.println("done");final int numElements = costMap_8_puzzle.size();stateToCostEntries_8_puzzle = new LinkedList<Entry>(costMap_8_puzzle.entrySet());System.err.print("Sorting entries...");Collections.sort(stateToCostEntries_8_puzzle, new Comparator<Entry>() {public int compare(final Entry e1, final Entry e2) {return e1.getValue() - e2.getValue();}});System.err.println("done");System.err.println("States in subset: " + numElements);}private void outputFifteenPuzzleData(final String filename,final DataOutputStream dos) {System.err.print("Writing file...");if (filename == null) {// Write values to stdout. User can redirect stdout to a file, if desired.for (int i = 0; i < configTable_15_puzzle.length; ++i) {final long config = configTable_15_puzzle[i];System.out.println((i + 1) + "," + config + "," +costTable_15_puzzle[i] + "," +Utility.longToString(config, numOfTiles));}} else {int i = 0;try {for ( ; i < costTable_15_puzzle.length; ++i) {dos.writeByte(costTable_15_puzzle[i]);}} catch (final IOException ioe) {System.err.println("Error: Cannot write entry " + i + " to file.");System.exit(1);} finally {try {if (dos != null) {dos.close();}} catch (final IOException ioe) { }}}System.err.println("done");}private void outputEightPuzzleData(final String filename,final DataOutputStream dos) {System.err.print("Writing file...");final Iterator<Entry> listIter = stateToCostEntries_8_puzzle.iterator();if (filename == null) {// Write values to stdout. User can redirect stdout to a file, if desired.int i = 1;while (listIter.hasNext()) {final Entry entry = listIter.next();final long config = entry.getKey();System.out.println(i + "," + config + "," + entry.getValue() +"," + Utility.longToString(config, numOfTiles));++i;}} else {int i = 0;try {while (listIter.hasNext()) {final Entry entry = listIter.next();dos.writeLong(((Long)entry.getKey()).longValue());dos.writeByte(((Byte)entry.getValue()).byteValue());++i;}} catch (final IOException ioe) {System.err.println("Error: Cannot write entry " + i + " to file.");System.exit(1);} finally {try {if (dos != null) {dos.close();}} catch (final IOException ioe) { }}}System.err.println("done");}private void breadthFirstSearch(final long boardConfig,final boolean[] tilesInSubset) {BFSNode currentState = new BFSNode(boardConfig);currentState.cost = 0;tempMap = new PrimitiveHashMap();tempMap.put(boardConfig, (byte)0);final Queue<BFSNode> queue = new LinkedList<BFSNode>();queue.add(currentState);byte previous = 1;while (true) {final char fromDirection = currentState.direction;if (fromDirection != 'R') {final BFSNode left = currentState.moveLeftNode(tilesInSubset);if (left != null) {final byte moves = tempMap.get(left.boardConfig);if (moves == PrimitiveHashMap.KEY_NOT_FOUND || left.cost < moves) {tempMap.put(left.boardConfig, left.cost);queue.add(left);}}}if (fromDirection != 'L') {final BFSNode right = currentState.moveRightNode(tilesInSubset);if (right != null) {final byte moves = tempMap.get(right.boardConfig);if (moves == PrimitiveHashMap.KEY_NOT_FOUND || right.cost < moves) {tempMap.put(right.boardConfig, right.cost);queue.add(right);}}}if (fromDirection != 'D') {final BFSNode up = currentState.moveUpNode(tilesInSubset);if (up != null) {final byte moves = tempMap.get(up.boardConfig);if (moves == PrimitiveHashMap.KEY_NOT_FOUND || up.cost < moves) {tempMap.put(up.boardConfig, up.cost);queue.add(up);}}}if (fromDirection != 'U') {final BFSNode down = currentState.moveDownNode(tilesInSubset);if (down != null) {final byte moves = tempMap.get(down.boardConfig);if (moves == PrimitiveHashMap.KEY_NOT_FOUND || down.cost < moves) {tempMap.put(down.boardConfig, down.cost);queue.add(down);}}}if (!queue.isEmpty()) {currentState = queue.remove();final byte movesRequired = currentState.cost;if (movesRequired > previous) {System.err.println("Generating boards with up to " + previous +" moves; map size: " + tempMap.size());previous = movesRequired;}} else {break;}}}private int indexFor(final long boardConfig, final boolean isFifteenPuzzle,final boolean[] tilesInSubset, final int[] tilePositions) {if (isFifteenPuzzle) {int hashCode = 0;for (int i = numOfTilesMinusOne; i >= 0; --i) {final int tile = (int)((boardConfig >> (i << 2)) & 0xF);if (tilesInSubset[tile]) {hashCode |= i << (tilePositions[tile] << 2);}}return hashCode;}return (int)boardConfig;}private boolean[] computeSubset(final byte dummyValue, final long boardConfig) {final boolean[] tilesInSubset = new boolean[numOfTiles];for (int pos = numOfTiles - 1; pos >= 0; --pos) {final byte tile = (byte)((boardConfig >> (pos << 2)) & 0xF);if (tile != dummyValue && tile != 0) {tilesInSubset[tile] = true;}}return tilesInSubset;}private static byte getArray(final String arrayString, final byte[] tiles,final int numOfTiles) {final StringTokenizer st = new StringTokenizer(arrayString, ",");final int numOfTokens = st.countTokens();// Validate the number of tiles entered.if (numOfTokens < numOfTiles) {System.out.println("Error: Input contains only " + numOfTokens +" of the " + numOfTiles + " tiles.");System.exit(1);} else if (numOfTokens > numOfTiles) {System.out.println("Error: Input exceeds required " +numOfTiles + " tiles.");System.exit(1);}// Create an array of String representations of the tile numbers.final String[] numStrings = new String[numOfTokens];int i = 0;while (st.hasMoreTokens()) {numStrings[i++] = st.nextToken();}// Make sure each string is a number.final int[] tilePositions = new int[numOfTiles];for (i = 0; i < tiles.length; ++i) {tiles[i] = -1;tilePositions[i] = -1;}for (i = 0; i < numStrings.length; ++i) {final String s = numStrings[i];try {final byte tile = Byte.parseByte(s);tiles[i] = tile;tilePositions[tile] = i;} catch (final NumberFormatException nfe) {if (!s.trim().toLowerCase().equals("x")) {System.err.println("Error: Expected integer or 'X' at index " + (i + 1) +", received '" + numStrings[i] + "'.");System.exit(1);}}}byte dummyTile = -1;// Make sure no tile number is missing from the input.for (i = 0; i < numOfTiles; ++i) {if (tilePositions[i] == -1) {if (i == 0) {System.err.println("Error: Tile 0 is missing for input.");System.exit(1);}dummyTile = (byte)i;break;}}// Replace 'X' (-1) tiles with the dummy value.for (i = 0; i < tiles.length; ++i) {if (tiles[i] == -1) {tiles[i] = dummyTile;}}return dummyTile;}public static void main(final String[] args) {if (args.length < 2 || args.length > 3) {System.err.println("Usage: java PatternDatabaseGenerator <num of tiles> <tile order> [filename]");System.exit(1);}int puzzleSize = 0;try {puzzleSize = Integer.parseInt(args[0].trim());if ((puzzleSize != 8) && (puzzleSize != 15)) {System.err.println("Error: Puzzle size must be either 8 or 15.");System.exit(1);}++puzzleSize;} catch (final NumberFormatException nfe) {System.err.println("Error: Puzzle size must be either 8 or 15.");System.exit(1);}final String tileOrder = args[1].trim();final byte[] tiles = new byte[puzzleSize];final byte dummyTile = getArray(tileOrder, tiles, puzzleSize);System.err.println("Using dummy tile: " + dummyTile);String filename = null;if (args.length == 3) {filename = args[2];}new PatternDatabaseGenerator(puzzleSize, Utility.byteArrayToLong(tiles), dummyTile, filename);} }

IDA*:第三階段由于使用不相交可加性的靜態(tài)模式數(shù)據(jù)庫(kù),所以不能像第二階段從目標(biāo)狀態(tài)找到初始狀態(tài)。

public static int dfs(int step, int h, int las) {if (step + h > bound) return step + h; // 從目標(biāo)開始找 f(n)剛開始最小 如果有更大的則更新 f(n) 反方向找 // if(layer[h]==-1)layer[h]=step; // if(step>layer[h]+15){ // System.out.printf("enter\n"); // return step+h; // }if (h == 0) { // 到達(dá)最終狀態(tài) 輸出g(n)即可// System.out.println(step);flg = 1;Rstep = step;return step;}int pos1 = pos;int ret = 127, x = pos1 / side, y = pos1 % side;int dx, dy, tar, ht, temp, i;for (i = 0; i < 4; i++) { //四個(gè)方向擴(kuò)展dx = x + u[i];dy = y + p[i];if (dx < 0 || dy < 0 || dx > side - 1 || dy > side - 1 || !ok(i, las)) continue;tar = (dx * side) + dy; //計(jì)算出擴(kuò)展出的新節(jié)點(diǎn)的一維坐標(biāo) 2,2 2*4+2= 10tmp[pos1] = tmp[tar]; // 0的坐標(biāo)等于擴(kuò)展出來的點(diǎn)的坐標(biāo) a.mat[10]=11;tmp[tar] = 0;//相當(dāng)于swap()pos = tar;//如果換一個(gè)評(píng)估函數(shù)呢//階段三 使用不相交模式數(shù)據(jù)庫(kù)得到評(píng)估函數(shù) ht值為分為的塊的h的和加起來//ht = getH(tmp);//ht = h - (Math.abs(xx[mat[pos1]] - dx) + Math.abs(yy[mat[pos1]] - dy)) + Math.abs(xx[mat[pos1]] - x) + Math.abs(yy[mat[pos1]] - y);if (step + ht <= bound) {for (int k = 0; k < side * side; k++) {result[step][k] = tmp[k];}//System.out.println(i);if(i==0){redir[step]='r';}else if(i==1){redir[step]='l';}else if(i==2){redir[step]='d';}else{redir[step]='u';}}temp = dfs(step + 1, ht, i);if (flg == 1) return temp;if (ret > temp) ret = temp;tmp[tar] = tmp[pos1];tmp[pos1] = 0;pos = pos1;}return ret;}

獲取h值:

static final int[] tilePositions = {-1, 0, 0, 1, 2, 1, 2, 0, 1, 3, 4, 2, 3, 5, 4, 5}; static final int[] tileSubsets = {-1, 1, 0, 0, 0, 1, 1, 2, 2, 1, 1, 2, 2, 1, 2, 2}; public static int getH(int [] tmp) {int index0 = 0, index1 = 0, index2 = 0;for (int pos = 15; pos >= 0; --pos) {final int tile = tmp[pos];if (tile != 0) {final int subsetNumber = tileSubsets[tile];switch (subsetNumber) {case 2:index2 |= pos << (tilePositions[tile] << 2);break;case 1:index1 |= pos << (tilePositions[tile] << 2);break;default:index0 |= pos << (tilePositions[tile] << 2);break;}}}return PuzzleConfiguration.costTable_15_puzzle_0[index0] +PuzzleConfiguration.costTable_15_puzzle_1[index1] +PuzzleConfiguration.costTable_15_puzzle_2[index2]; }

Result:

項(xiàng)目目錄: SearchingAstar: E:\University\AI\SearchingAstar3\SearchingAstar

NoInitial StateStepsTimeLimited Time
38, 13, 0, 6, 1, 15, 9, 14, 3, 4, 5, 11, 7, 2, 10, 12521.045s
42,9,5,11, 8,3,4,14, 7,10,1,12, 0,15,6,13510.070s
54,7,0,9,12,10,11,8,14,6,15,1,2,5,3,13560.028s
612, 10, 3, 2, 0, 7, 14, 9, 1, 15, 5, 6, 8, 4, 13, 11570.180s
712, 1, 5, 6, 2, 11, 7, 9, 14, 10, 0, 4, 15, 3, 13, 8500.009s
84, 6, 15, 13, 12, 9, 10, 2, 8, 0, 7, 3, 14, 5, 1, 11610.987s
915, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 1, 2, 0704.758s60s

Reference resources

(1)Ariel Felner,Richard E. Korf ,Disjoint pattern database heuristics
(2)Ariel Felner,Richard E. Korf,Sarit Hanan,Additive Pattern Database Heuristics

https://blog.csdn.net/u013009575/article/details/17140915

http://www.brian-borowski.com/software/puzzle/

http://www.ise.bgu.ac.il/engineering/upload/4273/naij.pdf

http://www.cnblogs.com/beilin/p/5981483.html

https://www.cnblogs.com/fujudge/p/7398153.html?utm_source=itdadao&utm_medium=referral

https://blog.csdn.net/shen_gan/article/details/8146027

https://www.gamedev.net/articles/programming/artificial-intelligence/a-pathfinding-for-beginners-r2003/

總結(jié)

以上是生活随笔為你收集整理的N-puzzle-Problem的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

精品亚洲网 | 中文字幕超清在线免费 | 最新av免费| 亚在线播放中文视频 | 日韩精品视频在线观看免费 | 亚洲作爱| 久久国产美女 | 久久av中文字幕片 | 能在线观看的日韩av | 国产亚洲精品久 | 婷婷丁香在线观看 | 国产区网址 | 麻豆传媒视频在线播放 | 国产一级黄 | 久草在线视频免费资源观看 | 婷婷射五月| 伊人天天综合 | 欧美一区二区三区免费观看 | 97视频在线免费 | 色婷婷狠狠五月综合天色拍 | 黄色亚洲免费 | 欧美精品国产综合久久 | 国产精品久久久久久久久久 | 亚洲精品视频在线播放 | 日日干夜夜骑 | 色吊丝在线永久观看最新版本 | 91精品亚洲影视在线观看 | 欧美狠狠操 | 公与妇乱理三级xxx 在线观看视频在线观看 | 97超碰.com | 91视频3p| 在线免费精品视频 | 色av婷婷 | 中文永久免费观看 | 色噜噜在线观看 | 激情久久一区二区三区 | 韩国精品在线观看 | 88av网站 | 亚洲久久视频 | 四虎8848免费高清在线观看 | 国产精品久久99精品毛片三a | 婷婷午夜天| 国产日韩高清在线 | 夜夜干夜夜| 国产精品乱码久久 | 四月婷婷在线观看 | 久久艹艹| 黄色三级免费网址 | av动图 | 日韩精选在线观看 | 99精品免费网 | 国产日产在线观看 | 福利电影久久 | 制服丝袜天堂 | 精品少妇一区二区三区在线 | 欧美三级免费 | 日日日日 | 国产午夜精品视频 | 天天干天天操天天射 | 麻豆果冻剧传媒在线播放 | 丁香资源影视免费观看 | 国产中文字幕在线播放 | 黄色免费观看网址 | 亚洲九九九在线观看 | 中文字幕成人 | 精品一区 在线 | 日韩综合色 | 国产成人精品a | 久久综合婷婷国产二区高清 | 91成人国产| 国产 日韩 在线 亚洲 字幕 中文 | 婷婷亚洲综合 | 中文字幕中文字幕在线中文字幕三区 | 精品视频免费观看 | av大全在线| 成人性生交大片免费看中文网站 | 亚洲精品五月天 | 涩涩成人在线 | 91亚瑟视频 | 天天人人 | 日韩精品一区二区三区第95 | 亚洲三级毛片 | 久久综合亚洲鲁鲁五月久久 | a黄色| 黄p网站在线观看 | 日韩欧美精品一区 | 粉嫩高清一区二区三区 | wwxxxx日本 | 91精选| 日日操操操| 韩日av一区二区 | 超碰av在线 | 97碰碰碰 | 99视频导航 | 国产精品亚洲综合久久 | 久久九九九九 | 国产一区二区三区四区在线 | 五月婷婷亚洲 | 91av片| 亚洲免费高清视频 | 欧美一级视频免费 | 天天狠狠干 | 天天干,夜夜操 | 欧美a在线看 | 五月天堂网 | 国产精品日韩在线 | 五月丁婷婷 | www国产在线 | 青青射 | 手机看国产毛片 | 涩涩伊人 | 一区二区三区视频网站 | 91精品久久久久久综合乱菊 | 99热999| 亚洲精品美女 | 国产美女视频一区 | 国产精品久久久久久久免费大片 | 九九九九精品 | 97在线视频免费看 | 丁香五月缴情综合网 | 韩日av一区二区 | 免费观看的黄色 | 91xav| 九色91福利 | 亚洲第二色 | 国产成人在线综合 | 欧美日韩一区二区在线观看 | zzijzzij亚洲成熟少妇 | 狠狠的操你 | 久久久免费观看完整版 | 亚洲观看黄色网 | 久久精品免视看 | 国产精品嫩草影视久久久 | 中文字幕最新精品 | 成人免费视频播放 | 天天干天天操天天 | 亚洲高清视频在线 | 最近乱久中文字幕 | 在线观看av不卡 | 最新av网站在线观看 | 中文字幕字幕中文 | 99精品色| 亚洲黄色av一区 | 国产成人a亚洲精品 | 开心色婷婷| 久久69av| 亚洲精品短视频 | 久久久久国产精品一区 | 99精品在线观看 | 91视频免费看网站 | 久久久久久综合网天天 | av在线色| 黄色91免费观看 | 青青河边草免费观看完整版高清 | 99久久精品免费看国产 | 成人免费视频网址 | 蜜臀久久99精品久久久久久网站 | 日韩视频精品在线 | 一区二区视频在线播放 | 欧美9999| 中文字幕在线高清 | 狠狠操狠狠干天天操 | 欧美成人h版电影 | 9992tv成人免费看片 | 91在线播放综合 | 日韩av图片 | 日韩在线免费小视频 | 亚洲高清免费在线 | 亚洲免费成人av电影 | 国产视频91在线 | 五月婷婷亚洲 | 国产亚洲一区二区三区 | 99免在线观看免费视频高清 | 久久精品国产免费看久久精品 | 日韩午夜三级 | 日日碰狠狠躁久久躁综合网 | 天天躁天天狠天天透 | 欧美日韩视频在线一区 | 欧美日韩高清一区二区 | 国产中文字幕在线观看 | 五月天色中色 | 91热爆视频 | 精品久久91 | 久久成人午夜视频 | 91在线看网站 | 狠狠久久| 欧美福利视频一区 | 天天摸夜夜操 | 国产精品999久久久 久产久精国产品 | 亚洲精品麻豆视频 | 丁香五月亚洲综合在线 | 国产精品区二区三区日本 | 国产精品久久久久永久免费看 | 亚洲狠狠干 | 日本黄色片一区二区 | 91av手机在线观看 | 免费视频 你懂的 | 日韩免费三级 | www.夜夜操.com | 99热官网 | 日本久久影视 | 天天骚夜夜操 | 欧美在线视频二区 | 国产特级毛片 | 亚洲精品免费观看视频 | 久久精品国产亚洲a | 99精品视频免费 | 91精品视频网站 | 美女视频黄网站 | 日韩二区在线播放 | 一级片黄色片网站 | 99视频在线免费观看 | www.com黄色 | 五月婷婷av在线 | 青青看片 | 91精品欧美一区二区三区 | 免费网站在线观看成人 | 日韩免费在线观看 | 午夜精品一区二区三区免费 | 国内久久精品 | 国产精品久久久久三级 | 免费欧美 | 国产一级做a爱片久久毛片a | 综合色狠狠 | 久久久国产精华液 | 日产中文字幕 | 久草视频在线新免费 | 亚洲精品一区二区三区在线观看 | 天天天天色射综合 | 精品久久久久免费极品大片 | 久久久亚洲影院 | 一区二区伦理电影 | 国产高清网站 | 欧美激情视频一区二区三区 | 2023年中文无字幕文字 | 91久久丝袜国产露脸动漫 | 99在线视频精品 | 久草在线播放视频 | 丁香婷婷激情国产高清秒播 | 欧美日韩视频在线一区 | 久久精品视频中文字幕 | 97福利在线 | 色婷婷久久久综合中文字幕 | av网站在线观看播放 | 久久亚洲影院 | 国产精品免费观看国产网曝瓜 | 亚洲精品高清一区二区三区四区 | 国产一区二区三区免费视频 | 日韩在线首页 | 婷婷色站 | 国产欧美综合在线观看 | 久草香蕉在线视频 | av电影在线观看 | 欧美 国产 视频 | 日韩在线视频一区二区三区 | 五月天婷婷视频 | 亚洲视频456 | 亚洲国产日韩在线 | 99久久精品免费 | 欧美视屏一区二区 | 日本黄色免费在线观看 | .精品久久久麻豆国产精品 亚洲va欧美 | 久久久久网址 | 91av在线精品 | 国产午夜麻豆影院在线观看 | 久久久久久久久久久精 | 免费黄色a级毛片 | 岛国大片免费视频 | 在线视频黄 | 亚洲国产成人高清精品 | 国产123区在线观看 国产精品麻豆91 | 五月天激情视频 | 亚洲天堂网在线视频观看 | av日韩不卡| 日韩在观看线 | 亚洲成av人影院 | 免费日p视频 | 国产精品久久网站 | 免费看污污视频的网站 | 久久免费国产精品1 | 日韩最新在线视频 | 久久精彩视频 | 狠狠色狠狠色终合网 | 日韩欧美高清一区二区 | 国产视频在 | 99国产精品久久久久老师 | 国产精品18久久久久久不卡孕妇 | 亚洲成色777777在线观看影院 | 狠狠色狠狠色合久久伊人 | 日韩精品三区四区 | 亚洲永久免费av | 91视频免费 | 又黄又爽又色无遮挡免费 | 精品久久中文 | 99久久久国产精品免费观看 | 久久天天躁狠狠躁夜夜不卡公司 | 日本久久电影网 | 午夜国产一区二区 | 91自拍视频在线 | 一级黄色片毛片 | 美女黄久久 | 天堂视频中文在线 | 国产福利精品一区二区 | 欧美精品一区在线发布 | 日韩一区二区三区不卡 | 久久午夜电影院 | 992tv在线观看网站 | 九九热视频在线免费观看 | 久久99久久精品国产 | 亚洲欧美日韩不卡 | 激情丁香久久 | 日韩欧美精品在线视频 | 一区三区视频在线观看 | 91插插视频 | 亚洲欧美日韩中文在线 | 在线观看免费中文字幕 | 综合婷婷 | 欧美一区二区三区在线 | 国产在线超碰 | 天天激情在线 | 五月婷婷综合激情网 | 国产精品免费麻豆入口 | 日韩电影在线视频 | 开心婷婷色 | 色综合久久久久综合体桃花网 | 超碰在线9 | 在线观看免费视频你懂的 | 亚洲不卡123 | 97精品欧美91久久久久久 | 91网站在线视频 | 四虎影视成人永久免费观看视频 | 国产馆在线播放 | 人人爽人人香蕉 | av福利在线导航 | 国产做aⅴ在线视频播放 | 精品二区视频 | 97视频在线免费 | 国产午夜精品视频 | 中文有码在线 | 国产日韩中文在线 | 国产91粉嫩白浆在线观看 | 国产日韩中文在线 | 国产一级片免费播放 | 亚洲一级二级三级 | 日本性动态图 | 免费日韩三级 | 香蕉视频免费看 | 在线观看完整版免费 | 欧美精品三级在线观看 | 日日夜夜综合 | 亚洲日本va午夜在线电影 | 久99久中文字幕在线 | av一区二区三区在线 | 日韩欧美视频在线 | 国产成人精品一区二区在线 | 天天射天天干天天爽 | 国产精品小视频网站 | 亚洲欧美精品一区 | 国产成人亚洲精品自产在线 | 日韩免费在线观看网站 | 99久久精品国产系列 | 色干综合 | 亚洲成人av片在线观看 | 久草电影在线观看 | 超碰97在线资源站 | 人人舔人人干 | 国产成人综合图片 | 香蕉视频在线免费 | 色婷婷国产在线 | 亚洲伊人天堂 | 高清视频一区二区三区 | 久久久久国产精品厨房 | 欧美日韩久久久 | 国产在线观看不卡 | 中文字幕色网站 | 日本激情视频中文字幕 | 精品视频在线免费观看 | 久久人人爽人人爽人人片av免费 | 五月婷婷操 | 99久久综合狠狠综合久久 | 国产美女精彩久久 | 国产原创中文在线 | 日韩在线一级 | 日韩午夜高清 | 狠狠狠操| 99色婷婷| 手机看片福利 | 日本精品久久久久 | 国产成人福利在线 | 中文字幕丰满人伦在线 | 激情视频免费观看 | 999久久国产精品免费观看网站 | av免费在线观看1 | 在线看黄网站 | 一区二区三区精品在线视频 | 9久久精品| 最新av免费| 福利一区在线视频 | 色老板在线视频 | 福利一区二区在线 | 国产999免费视频 | 国产日韩欧美在线观看 | 另类老妇性bbwbbw高清 | 91精品国产欧美一区二区 | 五月婷婷六月丁香 | 日韩中文在线观看 | 在线www色| 成人午夜精品久久久久久久3d | 二区视频在线观看 | 国产精品自产拍在线观看 | 久操97| 久久调教视频 | 狠狠色网 | 国内精品在线一区 | 午夜精品久久久久久久久久久 | 在线免费观看欧美日韩 | 奇米影音四色 | 激情小说网站亚洲综合网 | 日本黄色免费大片 | 狠狠干我 | 国产精品久久久久久久久久久杏吧 | 国产精品一区二区在线播放 | 一级理论片在线观看 | 狠狠久久 | 超碰在线94 | 国产色在线观看 | 久久艹免费 | 九热精品 | 国产在线a免费观看 | 久久99视频免费 | 久久久久久久国产精品视频 | 成人a级大片 | 91av视频免费在线观看 | 在线a人片免费观看视频 | 国产精品美女久久久久久久 | 精品嫩模福利一区二区蜜臀 | 91成人短视频在线观看 | 国产精品久久久久久久久久久久午夜 | 欧美性生活免费看 | 日产中文字幕 | 综合网久久 | 国产91在线观 | 97福利在线观看 | 国产拍揄自揄精品视频麻豆 | 久久1区 | 夜夜高潮夜夜爽国产伦精品 | 久久久久久久网站 | 人人草人 | 国产免费大片 | 国产人免费人成免费视频 | 一级欧美黄 | 国产伦精品一区二区三区在线 | 精品国产三级a∨在线欧美 免费一级片在线观看 | 91手机在线看片 | 欧美精品网站 | 国产一区观看 | 激情婷婷在线 | 久久色视频 | 天天躁日日 | 国产精品国产三级在线专区 | 天天操狠狠干 | 1024久久| 国产黄色精品在线 | 少妇bbbb搡bbbb桶 | 99色免费 | 91在线播放国产 | 日本在线观看一区二区三区 | 人人爱爱人人 | 毛片视频电影 | 在线色视频小说 | 国精产品999国精产品岳 | 日韩黄色在线 | 国产亚洲精品美女久久 | 中日韩免费视频 | 日韩欧美xxx | 国产人免费人成免费视频 | 成人资源在线 | av片一区 | 日韩在线第一 | 日本狠狠色 | 九九久久精品视频 | 在线中文字幕视频 | 久操视频在线播放 | 免费看的视频 | 国产精品门事件 | 日韩欧美成 | 国产一区播放 | 日韩专区在线 | 奇米7777狠狠狠琪琪视频 | 久久午夜电影院 | 蜜桃视频在线视频 | 在线观看激情av | 日本中文字幕高清 | 久久五月婷婷综合 | 国产99久久精品一区二区300 | av东方在线| 色综合久久久久综合99 | 17婷婷久久www | 视频在线观看入口黄最新永久免费国产 | 免费看国产a | 在线欧美日韩 | 日韩av中文字幕在线免费观看 | 日本韩国精品一区二区在线观看 | 五月婷丁香网 | 91av原创| 黄色一级在线视频 | 中文字幕在线观看免费观看 | 波多野结衣在线视频一区 | 国产欧美精品一区二区三区四区 | 国产色婷婷精品综合在线手机播放 | 97超碰资源| 日韩av不卡在线观看 | 在线观看久草 | av在线免费播放网站 | 五月天av在线 | 欧美日韩国产网站 | 亚州视频在线 | 久久国产乱 | 国产破处在线播放 | 国产亚洲精品久久久久久网站 | 国产剧情久久 | 在线观看日韩中文字幕 | 国产在线观看91 | 成人免费精品 | 在线中文字幕一区二区 | 国产精品色婷婷视频 | 狠狠色狠狠色综合日日小说 | 最近免费中文字幕大全高清10 | 青青草国产在线 | 黄色国产高清 | 国产一级一片免费播放放a 一区二区三区国产欧美 | 亚洲综合激情小说 | 久久99精品国产99久久6尤 | 日韩亚洲在线观看 | 看黄色.com | 日韩精选在线观看 | 欧美国产日韩在线视频 | 久热超碰| 最近能播放的中文字幕 | 久久综合99| av免费在线观| 二区三区毛片 | 久久99精品久久久久久久久久久久 | 色婷婷a | 色婷婷成人 | 久久久久久久久久久免费 | 国产不卡av在线 | 色综合在| 久久在草 | 在线观看蜜桃视频 | 日韩欧美综合在线视频 | 色综合天天做天天爱 | 中文字幕在线免费看 | 成人av片免费观看app下载 | 国产永久网站 | 麻豆视频在线观看 | aaawww| 日韩在线观看一区二区三区 | 黄色av免费 | 国产免费一区二区三区网站免费 | 免费国产视频 | 久久国产美女 | 欧美怡红院视频 | 日韩二区在线播放 | 精品国产午夜 | 最近日韩中文字幕中文 | 操操综合网 | 99综合久久| 欧美久久久久久久久久久久 | 国产成人91 | 色综合天天综合在线视频 | 免费看的黄色的网站 | 在线免费成人 | 18国产精品白浆在线观看免费 | 五月天中文字幕mv在线 | 91高清免费在线观看 | 久久伊人八月婷婷综合激情 | 国产精品99蜜臀久久不卡二区 | 成人一区在线观看 | 久久综合网色—综合色88 | 国产精品无av码在线观看 | av视屏在线播放 | 伊人婷婷网 | av中文字幕在线免费观看 | 日韩 国产| 精品中文字幕视频 | 伊人av综合 | 国产精品淫 | 亚洲全部视频 | 亚洲激情av| 午夜久久精品 | 久久精品牌麻豆国产大山 | 欧美嫩草影院 | 亚州欧美精品 | 2023av在线| 最近中文字幕在线 | 国产精品成人一区二区三区吃奶 | 九九热在线观看 | 日韩免费视频播放 | 午夜精品剧场 | 96av麻豆蜜桃一区二区 | 毛片区 | 2019中文字幕网站 | 在线观看小视频 | 正在播放国产91 | 丁香激情五月婷婷 | 91av蜜桃 | 国产高清 不卡 | 免费亚洲黄色 | 日本久久综合视频 | 又爽又黄又无遮挡网站动态图 | 国产精品视频内 | 精品国产三级a∨在线欧美 免费一级片在线观看 | 91精品资源 | 91av免费在线观看 | 97狠狠操 | www.久久爱.cn | 97人人澡人人添人人爽超碰 | 操少妇视频 | 国产精品色婷婷 | 国产精品久久久久久久久久久久久久 | 亚洲国产日韩精品 | 一级a毛片高清视频 | 2021国产精品视频 | 国产精品999久久久 久产久精国产品 | 中文字幕在线精品 | 亚洲尺码电影av久久 | 精品在线免费观看 | 国产91精品看黄网站在线观看动漫 | 精品夜夜嗨av一区二区三区 | 日韩午夜剧场 | 国产黄色成人av | 2023年中文无字幕文字 | 亚洲尺码电影av久久 | 亚洲一区日韩在线 | 久热超碰| 亚洲视频国产 | 丁香一区二区 | 超碰av在线播放 | 天天干,天天射,天天操,天天摸 | 久久毛片网站 | 在线只有精品 | av黄色影院 | 亚洲 中文字幕av | 亚洲精品电影在线 | 久久中文精品视频 | wwwwwww黄| 深爱婷婷久久综合 | 在线观看免费黄视频 | 激情欧美丁香 | 在线欧美a| 波多在线视频 | 日韩 国产 | 日韩区欠美精品av视频 | 免费福利在线视频 | 国产 日韩 欧美 中文 在线播放 | 在线视频区| 天天操天天舔天天爽 | 成人免费在线观看入口 | 欧美在线你懂的 | 久久久麻豆精品一区二区 | 欧美aⅴ在线观看 | 在线天堂中文在线资源网 | 欧美日韩午夜 | 麻豆91在线| 一级一片免费视频 | 天天射天天干天天操 | 91久久精品日日躁夜夜躁国产 | 亚洲午夜精品一区二区三区电影院 | 国产精品原创 | www.亚洲在线 | 人人射人人射 | 草久久av | 色悠悠久久综合 | 日韩av高清在线观看 | 黄色avwww| 中文字幕在线视频第一页 | 亚洲免费婷婷 | 国产91免费观看 | 在线观看日韩免费视频 | 在线看av的网址 | av中文字幕不卡 | 免费在线精品视频 | 日韩久久久久久久久久久久 | 久久成电影 | 婷婷午夜激情 | 国产精品123 | 超碰在线最新网址 | 精品国产精品久久一区免费式 | 天天躁日日| 国产精品99久久免费观看 | 美女视频黄的免费的 | 超碰在线资源 | 亚洲一区二区三区四区精品 | 国产高清在线一区 | 在线91av | 91在线视频免费91 | 国产91av视频在线观看 | 久久视频国产精品免费视频在线 | 天天射天 | 精品一区二区三区电影 | 93久久精品日日躁夜夜躁欧美 | 天天综合网~永久入口 | 欧美一级久久久久 | 久久精品国产精品 | 国产精品白丝av | av线上看 | av电影免费在线播放 | www操操| 亚洲成人精品久久 | 色欧美视频| 操操操av | 97视频在线播放 | 五月婷婷久草 | 91综合久久一区二区 | 99热99热| 免费看的毛片 | 精品国产激情 | 天天夜夜操 | 波多野结衣资源 | 国产资源免费 | 国产一区电影在线观看 | 色综合久久88色综合天天免费 | 在线观看电影av | 中文字幕资源网在线观看 | 久久久久久久久久久免费视频 | 国产精品久久久久免费 | 免费在线观看不卡av | 精品在线亚洲视频 | 国产精品久久久久久av | 日韩在线观看视频一区二区三区 | 亚洲激情av | 久久视频免费在线观看 | 五月花婷婷 | 成人小视频在线播放 | 最近中文字幕mv免费高清在线 | 国产精品一区二区三区视频免费 | 欧美日韩中文国产一区发布 | 在线精品一区二区 | 亚洲成成品网站 | 五月激情丁香 | 超碰在线cao | 久久再线视频 | 天天曰天天干 | 五月婷婷国产 | 亚洲精品综合一区二区 | 99精品黄色 | 国产一卡二卡四卡国 | 成人黄色中文字幕 | 欧美性超爽 | 日本不卡一区二区三区在线观看 | 欧美激情操 | 国产在线a免费观看 | 探花视频在线观看免费版 | 在线观看日韩中文字幕 | 男女拍拍免费视频 | 四虎成人精品永久免费av九九 | 日韩欧美有码在线 | 日韩欧美视频 | 99精品视频免费全部在线 | 亚洲午夜久久久久久久久电影网 | 中文字幕国内精品 | 涩涩网站在线观看 | 国产一区久久久 | 久久久鲁 | 免费久久99精品国产婷婷六月 | 国产二级视频 | 国产不卡一二三区 | 日韩在线看片 | 成人a级黄色片 | 美腿丝袜av | 午夜精品久久久久久久99水蜜桃 | 夜夜躁日日躁 | 成人在线网站观看 | 欧美少妇xx | 久久系列 | 黄色在线视频网址 | 亚洲三级性片 | 天天干天天做天天爱 | 精品美女久久久久久免费 | 九七人人干 | 久产久精国产品 | 亚洲精品乱码久久久久久久久久 | 91亚洲国产成人久久精品网站 | 久久激情五月丁香伊人 | 国产裸体永久免费视频网站 | 欧美在线一二 | 视频在线一区二区三区 | 国产高清专区 | 色综合久久88色综合天天6 | 激情综合网色播五月 | 午夜性生活| 午夜美女福利直播 | 又色又爽又黄 | 婷婷综合导航 | 日本午夜免费福利视频 | 天天综合网久久 | 91av99| 日韩影视在线观看 | 亚洲九九精品 | 激情深爱.com | 91黄视频在线观看 | 久久久久成人免费 | 欧美激情操 | 特级黄录像视频 | 亚洲黄色精品 | 欧美成人91 | 天天摸日日操 | 亚洲无吗天堂 | 亚洲夜夜网 | 黄色高清视频在线观看 | 国产在线不卡精品 | 97视频总站| 中文字幕在线网 | 久久综合久久鬼 | 久久精品99 | 香蕉视频国产在线观看 | 国产精品嫩草影视久久久 | 国产精品久久婷婷六月丁香 | 一区二区中文字幕在线观看 | 午夜精品久久久 | 午夜视频在线观看一区二区 | 欧美日韩二三区 | 久久久久久久福利 | 久久精品视频在线免费观看 | 色婷婷狠狠五月综合天色拍 | 婷婷丁香色 | 国产精品二区在线观看 | 欧美影院久久 | 国产99久| 国产精品一区二区久久久 | 一二三区高清 | 超碰在线个人 | 天天爱天天 | 成人在线视频免费看 | 国产这里只有精品 | 国产精品一区二区你懂的 | 国产精品福利在线观看 | 久久久久久久久久久影院 | www.狠狠操.com | 在线视频在线观看 | 久久久夜色 | 国产成人99av超碰超爽 | 成人精品国产免费网站 | 国产小视频在线播放 | 午夜精品一区二区三区免费 | 在线观看不卡视频 | 国产999精品久久久 免费a网站 | 欧美另类一二三四区 | 亚洲狠狠丁香婷婷综合久久久 | 国产中文视频 | 久久中文字幕视频 | 激情综合网五月婷婷 | 久久精品之 | 国产精品 日韩精品 | 亚洲最大免费成人网 | 久久国产免费 | 日韩精品欧美专区 | 在线观看黄av | 欧美日韩一区二区视频在线观看 | 国产日产高清dvd碟片 | 天天天天天天干 | 色五丁香| av久久在线 | 99人久久精品视频最新地址 | 精品免费视频. | 国产视频在线免费观看 | 国产成人av综合色 | www免费| 欧美视频在线二区 | 久久国产精品99久久人人澡 | 免费视频黄色 | 国产精品 中文字幕 亚洲 欧美 | 免费观看国产成人 | 欧美日韩中文视频 | 夜色成人av| 久久免费av| 色五月成人 | 国产精品18p | 免费a v网站 | 97超碰人| 在线观看v片 | 精品免费久久久久久 | 超碰日韩在线 | 夜夜视频欧洲 | 极品美女被弄高潮视频网站 | 精品亚洲一区二区三区 | 日日爱av| 亚洲毛片久久 | 黄色视屏av| 综合色爱 | 国产91成人 | 欧美日韩国产区 | 深爱激情av | 国产精品乱码高清在线看 | 国产福利91精品一区二区三区 | 久久艹中文字幕 | 四虎影视av | 超碰在线最新网址 | 精品 激情| 高清中文字幕 | 国产一二区视频 | 久久九九国产精品 | 国产成人亚洲在线观看 | 欧美一区二区精美视频 | 天天躁日日躁狠狠躁av麻豆 | 91免费在线视频 | 97在线精品| 色99在线| 国产午夜精品一区二区三区四区 | 粉嫩av一区二区三区入口 | 日韩在线观看你懂的 | 91成人国产 | 日韩资源在线观看 | 国产精品 日韩 欧美 | 欧美男同视频网站 | 亚洲成人第一区 | 99国产精品久久久久久久久久 | 久久你懂得 | 国产又粗又猛又爽 | 中文字幕日韩精品有码视频 | 日日操网| 久久爱992xxoo | 国产在线精品一区二区不卡了 | 黄色在线免费观看网站 | 亚洲精品在线免费 | 99久久精品无免国产免费 | 国产麻豆电影 | 亚洲一区二区精品3399 | 国产呻吟在线 | 欧美日韩一区二区三区视频 | 欧美精品一区二区蜜臀亚洲 | 欧美伦理一区二区 | 亚洲永久精品一区 | 国产精品久久99综合免费观看尤物 | 亚洲精品乱码白浆高清久久久久久 | 激情欧美一区二区三区 | 一级α片免费看 | 国产高清一区二区 | 免费人成网ww44kk44 | 国产最新福利 | 成人h视频在线播放 | 久久国产精品免费观看 | 免费三级影片 | 精品一区二区三区久久久 | 久久久久国产一区二区三区 | 日日日干 | 成人黄色电影在线播放 | 天天色天天爱天天射综合 | 2019精品手机国产品在线 | av免费试看 | 麻花豆传媒mv在线观看网站 | 欧美午夜性生活 | 久久涩涩网站 | 亚洲精品三级 | 婷婷五情天综123 | 亚洲九九九在线观看 | 国产精品96久久久久久吹潮 | 精品久久久久久久 | 成人午夜精品 | 午夜精品久久久久久久久久 | 99这里都是精品 | 欧美视频日韩 | 国产专区在线 | 国产成人一区二区三区久久精品 | 国产成人在线精品 | 亚洲 欧美 变态 国产 另类 | 97在线精品视频 | 福利一区二区三区四区 | 91大神免费视频 | 国产成年免费视频 | 手机色站| 成年人在线免费看视频 | 日韩影视精品 | 国产男女无遮挡猛进猛出在线观看 | 欧美福利片在线观看 | 五月婷婷在线视频观看 | 色综合色综合久久综合频道88 | 亚洲资源视频 | 久久五月婷婷丁香 | av超碰在线| 99色亚洲 | 男女视频91 | 国产精品日韩久久久久 | 一个色综合网站 | 操天天操 | 中文永久免费观看 | 成片免费观看视频 | 国产在线91在线电影 | 最新99热 | 91污视频在线观看 | 99久久9| 亚洲免费在线观看视频 | 五月天久久综合 | 国产黄网站在线观看 | 91精品福利在线 | 亚洲九九 | 天天色.com |