Java 用IDA*和曼哈顿解决难题NxN
给定游戏,它从包含数字瓷砖的方形网格开始 从1到N,一个空块用X表示。目标是根据瓷砖的编号放置瓷砖 移动是通过将磁贴从左、右、上、下移动到空磁贴的位置来完成的。我必须使用IDA*和曼哈顿方法来解决这个问题 我的目标是产出 1.在第一行输出从起始状态到目标状态的“最佳”路径的长度 2.为了达到最终状态而解决问题的步骤。台阶有左、右、上、下 以下是我目前正在开发3x3解决方案的代码:Java 用IDA*和曼哈顿解决难题NxN,java,algorithm,Java,Algorithm,给定游戏,它从包含数字瓷砖的方形网格开始 从1到N,一个空块用X表示。目标是根据瓷砖的编号放置瓷砖 移动是通过将磁贴从左、右、上、下移动到空磁贴的位置来完成的。我必须使用IDA*和曼哈顿方法来解决这个问题 我的目标是产出 1.在第一行输出从起始状态到目标状态的“最佳”路径的长度 2.为了达到最终状态而解决问题的步骤。台阶有左、右、上、下 以下是我目前正在开发3x3解决方案的代码: /** * * Problem Name: Eight Algorithm: IDA* (Iterative
/**
*
* Problem Name: Eight Algorithm: IDA* (Iterative deepening A*) using Manhattan Distance Heuristic
* Source: AI: A Modern Approach
*
*/
// Beware my messy code follows!
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
*
*
*
*
* @class used to keep State Machine of Eight Puzzle with f,g,h along with board
*
*/
class StateEightPuzzle {
private int f, g, h;
private StringBuilder stateofBoard;
private int xEmptyTile, yEmptyTile;
private int pre;
public void setStateofBoard(StringBuilder stateofBoard) {
this.stateofBoard = stateofBoard;
}
public void setPre(int pre) {
this.pre = pre;
}
public void setXEmptyTile(int xEmptyTile) {
this.xEmptyTile = xEmptyTile;
}
public void setYEmptyTile(int yEmptyTile) {
this.yEmptyTile = yEmptyTile;
}
public void setF(int f) {
this.f = f;
}
public void setG(int g) {
this.g = g;
}
public void setH(int h) {
this.h = h;
}
public int getPre() {
return pre;
}
public int getXEmptyTile() {
return xEmptyTile;
}
public int getYEmptyTile() {
return yEmptyTile;
}
public StringBuilder getStateofBoard() {
return stateofBoard;
}
public int getF() {
return f;
}
public int getG() {
return g;
}
public int getH() {
return h;
}
}
/**
*
* @class used as return type where flimit is used as current flimit and sol indicates whether
* solution is found
*
*/
class ReturnResult {
int flimit;
StateEightPuzzle sol;
}
public class Main {
/**
* @param args
*/
static int flag;
static int[] tracePath;
static private int ROWSIZE = 3;
static private int BOARDSIZE = 9;
/*
*
* function used to see whether the current Eight puzzle can be solvable that is can we subjugate
* our beloved using inversion permutation
*/
public static boolean isSolvable(String dpState) {
int inversion = 0;
for (int i = 0; i < BOARDSIZE; i++)
for (int j = i + 1; j < BOARDSIZE; j++)
if (dpState.charAt(i) > '0' && dpState.charAt(j) > '0'
&& dpState.charAt(i) > dpState.charAt(j))
inversion++;
if (inversion % 2 == 1)
return false;
else
return true;
}
/*
*
* getManhattanDistance returns Manhattan distance between current Node of Eight puzzle State
* Machine and Goal State(Final Destination)
*/
public static int getManhattanDistance(StringBuilder knightBoard) {
int manhattanVal = 0;
for (int i = 0; i < ROWSIZE; i++)
for (int j = 0; j < ROWSIZE; j++) {
int pos = i * ROWSIZE + j;
int val = (knightBoard.charAt(pos) - '0') - 1;
if (val == -1)
continue;
manhattanVal = manhattanVal + Math.abs((val / ROWSIZE) - i) + Math.abs((val % ROWSIZE) - j);
}
return manhattanVal;
}
/**
*
*
*
* @param stat
* @param x
* @param y
* @return
*
* function used to generate next State Machine of Eight Puzzle aka Successor Node(Child
* Node) of Current State(Father Node)
*
*/
public static StateEightPuzzle findSuccessor(StateEightPuzzle fatherNode, int x, int y, int pre) {
int nextXCordiante, nextYCordiante;
nextXCordiante = fatherNode.getXEmptyTile();
nextYCordiante = fatherNode.getYEmptyTile();
StateEightPuzzle childNode = new StateEightPuzzle();
if ((nextXCordiante + x) < 0 || (nextYCordiante + y) < 0 || (nextXCordiante + x) > (ROWSIZE - 1)
|| (nextYCordiante + y) > (ROWSIZE - 1)) {
flag = 0;
return childNode;
}
int nextEmptyTile = (nextXCordiante + x) * ROWSIZE + (nextYCordiante + y);
StringBuilder s1 = new StringBuilder(fatherNode.getStateofBoard());
char ch = s1.charAt(nextEmptyTile);
s1.setCharAt(nextEmptyTile, '0');
s1.setCharAt(ROWSIZE * nextXCordiante + nextYCordiante, ch);
childNode.setStateofBoard(s1);
childNode.setXEmptyTile(nextXCordiante + x);
childNode.setYEmptyTile(nextYCordiante + y);
childNode.setG(fatherNode.getG() + 1);
childNode.setH(getManhattanDistance(s1));
childNode.setPre(pre);
int maxfValue = (fatherNode.getF()) > (childNode.getG() + childNode.getH()) ? fatherNode.getF()
: (childNode.getG() + childNode.getH());
childNode.setF(maxfValue);
flag = 1;
return childNode;
}
/**
*
* @param init
* @param flimit
* @param res
* @return function known as Iterative Deepening DFS for A* which uses f-cost for limiting it
* search depth. Once the search inside a given contour has been completed , a new
* iteration is started with new f-cost for the next DFS-CONTOUR.pls consult Artificial
* Intelligence A Modern Approach, 1st edition by Approach By Russell
*
*/
public static ReturnResult DFS_CONTOUR(StateEightPuzzle Node, int flimit, ReturnResult res) {
int newf = Integer.MAX_VALUE;
ReturnResult resTemp = new ReturnResult();
StateEightPuzzle stat;
tracePath[Node.getG()] = Node.getPre();
// distance matrix for Eight Puzzle which helps to get successor
int dist[][] = {{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
// if current node exceeds flimit return it as flimit
if (Node.getF() > flimit) {
resTemp.flimit = Node.getF();
resTemp.sol = null;
return resTemp;
}
// I see : IDA* is going to give me juicy cool!
if (Node.getH() == 0) {
resTemp.flimit = flimit;
resTemp.sol = Node;
String sol = "uldr";
for (int i = 1; i <= Node.getG(); i++)
System.out.print(sol.charAt(tracePath[i]));
System.out.println("");
return resTemp;
}
// create next valid successor
for (int i = 0; i < 4; i++) {
if (Math.abs(i - Node.getPre()) == 2)
continue;
stat = findSuccessor(Node, dist[i][0], dist[i][1], i);
if (flag == 0)
continue;
resTemp = DFS_CONTOUR(stat, flimit, res);
if (resTemp.sol != null) {
resTemp.flimit = res.flimit;
return resTemp;
}
newf = resTemp.flimit < newf ? resTemp.flimit : newf;
}
resTemp.flimit = newf;
resTemp.sol = null;
return resTemp;
}
public static void main(String[] args) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
String s_2;
while ((s_2 = in.readLine()) != null) {
String str = "";
tracePath = new int[1000];
int emptySquare = 0;
String[] s2 = s_2.split("\\s+");
for (int i = 0; i < s2.length; i++) {
if (s2[i].equals("x") == false)
str += s2[i];
else
str += "0";
}
if (isSolvable(str) == false) {
System.out.println("unsolvable");
} else {
StringBuilder str_bld = new StringBuilder(str);
for (int i = 0; i < str_bld.length(); i++)
if (str_bld.charAt(i) == '0') {
emptySquare += i;
break;
}
// Create Initial Eight puzzle State Machine and let him dance
// with
// prima donna :-)
StateEightPuzzle init = new StateEightPuzzle();
init.setStateofBoard(str_bld);
init.setG(0);
init.setH(getManhattanDistance(str_bld));
init.setF(init.getH() + init.getG());
init.setXEmptyTile(emptySquare / ROWSIZE);
init.setYEmptyTile(emptySquare % ROWSIZE);
init.setPre(5);
int flimit = init.getF();
ReturnResult result = new ReturnResult();
result.flimit = flimit;
result.sol = init;
// loop loop i m a strange loop living a mundane life with hopes
for (;;) {
ReturnResult resTemp = DFS_CONTOUR(init, flimit, result);
if (resTemp.sol != null) {
break;
}
flimit = resTemp.flimit;
}
}
}
}
}
/**
*
*问题名称:八算法:使用曼哈顿距离启发式的IDA*(迭代深化A*)
*资料来源:人工智能:现代方法
*
*/
//小心我下面的乱码!
导入java.io.BufferedReader;
导入java.io.IOException;
导入java.io.InputStreamReader;
/**
*
*
*
*
*@class用于保存带有f、g、h和棋盘的八个拼图的状态机
*
*/
类stateightpuzzle{
私有整数f,g,h;
私人舷梯;
私有int-xemptyle,yemptyle;
私人int pre;
公用空心板状态(StringBuilder状态){
this.stateofBoard=板的状态;
}
公共无效setPre(int-pre){
this.pre=pre;
}
公共void setxemptyle(int-xemptyle){
this.xemptyle=xemptyle;
}
公共void setyemptyle(int-yemptyle){
this.yemptyle=yemptyle;
}
公共无效setF(int f){
这个。f=f;
}
公共无效设置(int g){
这个.g=g;
}
公共空间塞斯(内西){
这个,h=h;
}
公共int getPre(){
返回预处理;
}
public int getxemptyle(){
返回豁免;
}
public int getyemptyle(){
返回Yemptyle;
}
公共StringBuilder getStateofBoard(){
返回板的状态;
}
公共int getF(){
返回f;
}
公共int getG(){
返回g;
}
公共int getH(){
返回h;
}
}
/**
*
*@class用作返回类型,其中flimit用作当前flimit,sol指示是否
*找到了解决方案
*
*/
班级返回结果{
国际飞行;
StateEightPuzzle sol;
}
公共班机{
/**
*@param args
*/
静态int标志;
静态int[]轨迹路径;
静态私有int ROWSIZE=3;
静态专用int BOARDSIZE=9;
/*
*
*函数用于查看当前的八个谜题是否可以解决,即我们可以征服吗
*我们的爱人使用反转排列
*/
公共静态布尔可解(字符串状态){
int反转=0;
对于(int i=0;i'0'和&dpState.charAt(j)>'0'
&&dpState.charAt(i)>dpState.charAt(j))
倒置++;
如果(反转%2==1)
返回false;
其他的
返回true;
}
/*
*
*GetManhaAttandInstance返回八个谜题状态的当前节点之间的曼哈顿距离
*机器和目标状态(最终目的地)
*/
公共静态int GetManhattandInstance(StringBuilder knightBoard){
int manhattanVal=0;
对于(int i=0;i(行大小-1)
||(NextyCordante+y)>(行大小-1)){
flag=0;
返回子节点;
}
int-nextEntytile=(nextxcordante+x)*行大小+(nextcordante+y);
StringBuilder s1=新的StringBuilder(父节点.getStateofBoard());
char ch=s1.charAt(下一步);
s1.setCharAt(nextentile,'0');
s1.设置字符(行大小*下一个字符+下一个字符,ch);
childNode.setStateofBoard(s1);
setxemptyle(nextxcordante+x);
setyemptyle(nextYCordiante+y);
setG(fatherNode.getG()+1);
setH(getManhattanDistance(s1));
setPre(pre);
int maxfValue=(fatherNode.getF())>(childNode.getG()+childNode.getH())?fatherNode.getF()
:(childNode.getG()+childNode.getH());
setF(maxfValue);
flag=1;
返回子节点;
}
/**
*
*@param init
*@param-flimit
*@param res
*@return函数称为A*的迭代深化DFS,它使用f-cost来限制它
*搜索深度。一旦给定轮廓内的搜索完成,新的
*下一个DFS-CONTOUR将以新的f成本开始迭代。请咨询人工
*《现代方法的智能》,第1版,拉塞尔的方法
*
*/
公共静态ReturnResult DFS_CONTOUR(StateEightPuzzle节点、int flimit、ReturnResult res){
int newf=Integer.MAX_值;
ReturnResult resTemp=新的ReturnResult();
StateEightPuzzle统计;
tracePath[Node.getG()]=Node.getPre();
//八个谜题的距离矩阵,有助于获得后续答案
int dist[][]={-1,0},{0,-1},{1,0},{0,1};
//如果当前节点超过flimit,则将其作为flimit返回
if(Node.getF()>flimit){
resTemp.flimit=Node.getF();