Java 用IDA*和曼哈顿解决难题NxN

Java 用IDA*和曼哈顿解决难题NxN,java,algorithm,Java,Algorithm,给定游戏,它从包含数字瓷砖的方形网格开始 从1到N,一个空块用X表示。目标是根据瓷砖的编号放置瓷砖 移动是通过将磁贴从左、右、上、下移动到空磁贴的位置来完成的。我必须使用IDA*和曼哈顿方法来解决这个问题 我的目标是产出 1.在第一行输出从起始状态到目标状态的“最佳”路径的长度 2.为了达到最终状态而解决问题的步骤。台阶有左、右、上、下 以下是我目前正在开发3x3解决方案的代码: /** * * Problem Name: Eight Algorithm: IDA* (Iterative

给定游戏,它从包含数字瓷砖的方形网格开始 从1到N,一个空块用X表示。目标是根据瓷砖的编号放置瓷砖 移动是通过将磁贴从左、右、上、下移动到空磁贴的位置来完成的。我必须使用IDA*和曼哈顿方法来解决这个问题

我的目标是产出

1.在第一行输出从起始状态到目标状态的“最佳”路径的长度

2.为了达到最终状态而解决问题的步骤。台阶有左、右、上、下

以下是我目前正在开发3x3解决方案的代码:


/**
 *
 * 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();