普林斯顿算法课第四周作业
2015-02-16 10:14
323 查看
8 Puzzle
作业地址:http://coursera.cs.princeton.edu/algs4/assignments/8puzzle.html----------------------------------------------------------------------------------------------------------
第四周作业 8 Puzzle
8 puzzle 是一个经典的拼图问题
将九宫格内乱序的8个数字按顺序整理好,一次只能移动一个数字到空位当中。
作业中提供的思路是Best-first search(最好优先搜索)
首先定义一个Search Node,记录初始到达当前状态的移动次数和上一个状态。
通过不断从优先级队列中取出Search Node 去寻找下一级的状态,并在其中找到最符合优先级的结果。
而要确定优先级就要使用以下两个方法:
Hamming priority function:表示不在目标位置的数目
Manhattan priority function:所有方块距离目标位置之和。
然后是需要注意的几个问题:
1.A critical optimization
防止重复状态的出现,需要进行判断
2.Game Tree 将状态以搜索树的方式储存,每一个节点对应一个状态。在每一步中,用A*算法
删除优先级队列中权值最小的那个节点。
3.Detecting infeasible puzzles
有一些初始状态是不可能得到目的状态的。题目中给我们的方法是,将同行的两个数进行交换,
如果其中一个得到目标解,那么另外一个则不可能。
最后有一些方法可能使用不当,很多都超时了
代码如下:
Board.java
import java.util.Arrays; import java.util.Comparator; public class Board { private final int[][] blocks; private final int N; // construct a board from an N-by-N array of blocks // (where blocks[i][j] = block in row i, column j) public Board(int[][] blocks){ N = blocks.length; this.blocks = new int []; for (int i=0; i<N; i++){ this.blocks[i] = Arrays.copyOf(blocks[i], N); } } // board dimension N public int dimension(){ return this.N; } // number of blocks out of place public int hamming(){ int i_hamming = 0; for (int i=0; i<N; i++){ for (int j=0; j<N && i+j < 2*N - 2; j++){ if (blocks[i][j] != i*N + j + 1){ i_hamming++; } } } return i_hamming; } // sum of Manhattan distances between blocks and goal public int manhattan(){ int i_manhattan = 0; for (int i=0; i<N; i++){ for (int j=0; j<N; j++){ if (blocks[i][j] != 0){ i_manhattan += Math.abs((blocks[i][j] - 1) % N - j) + Math.abs((blocks[i][j] - 1) / N - i); } } } return i_manhattan; } // is this board the goal board? public boolean isGoal(){ return this.hamming() == 0; } // a board obtained by exchanging two adjacent blocks in the same row public Board twin(){ int[][] twinBoard = new int ; for (int i=0; i<N; i++){ for (int j=0; j<N; j++){ twinBoard[i][j] = blocks[i][j]; } } if (blocks[0][0] != 0 && blocks[0][1] != 0){ int temp = twinBoard[0][0]; twinBoard[0][0] = twinBoard[0][1]; twinBoard[0][1] = temp; }else{ int temp = twinBoard[1][0]; twinBoard[1][0] = twinBoard[1][1]; twinBoard[1][1] = temp; } return new Board(twinBoard); } // does this board equal y? public boolean equals(Object y){ if (y == this) return true; if (y == null) return false; if (y.getClass() != this.getClass()){ return false; } Board thatBoard = (Board)y; if (this.N != thatBoard.N){ return false; } int[][] arr_thatBoard = thatBoard.blocks; for (int i=0; i<N; i++){ for (int j=0; j<N; j++){ if (blocks[i][j] != arr_thatBoard[i][j]){ return false; } } } return true; } // all neighboring boards public Iterable<Board> neighbors(){ int blank_i = N; int blank_j = N; for (int i=0; i<N; i++){ for (int j=0; j<N; j++){ if (blocks[i][j] == 0){ //this is where the blank is blank_i = i; blank_j = j; } } } MinPQ<Board> q = new MinPQ<Board>(new Comparator<Board>() { public int compare(Board o1, Board o2) { if (o1.manhattan() < o2.manhattan()) return -1; else if (o1.manhattan() == o2.manhattan()) return 0; else return 1; } }); if (blank_j - 1 >= 0){ int[][] arr_temp = getCopy(); arr_temp[blank_i][blank_j] = arr_temp[blank_i][blank_j - 1]; arr_temp[blank_i][blank_j - 1] = 0; q.insert(new Board(arr_temp)); // arr_temp = blocks.clone(); } if (blank_j + 1 < N){ int[][] arr_temp = getCopy(); arr_temp[blank_i][blank_j] = arr_temp[blank_i][blank_j + 1]; arr_temp[blank_i][blank_j + 1] = 0; q.insert(new Board(arr_temp)); // arr_temp = blocks.clone(); } if (blank_i - 1 >= 0){ int[][] arr_temp = getCopy(); arr_temp[blank_i][blank_j] = arr_temp[blank_i - 1][blank_j]; arr_temp[blank_i - 1][blank_j] = 0; q.insert(new Board(arr_temp)); // arr_temp = blocks.clone(); } if (blank_i + 1 < N){ int[][] arr_temp = getCopy(); arr_temp[blank_i][blank_j] = arr_temp[blank_i + 1][blank_j]; arr_temp[blank_i + 1][blank_j] = 0; q.insert(new Board(arr_temp)); // arr_temp = blocks.clone(); } return q; } // string representation of the board (in the output format specified below) public String toString() { StringBuilder s = new StringBuilder(); s.append(N + "\n"); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { s.append(String.format("%2d ", blocks[i][j])); } s.append("\n"); } return s.toString(); } private int[][] getCopy(){ int[][] result = new int []; for (int i=0; i<N; i++){ result[i] = Arrays.copyOf(blocks[i], N); } return result; } public static void main(String[] args) { // create initial board from file In in = new In(args[0]); int N = in.readInt(); int[][] blocks = new int ; for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) blocks[i][j] = in.readInt(); Board initial = new Board(blocks); StdOut.println(initial); StdOut.println(initial.hamming()); } }
Solver.java
import java.util.Comparator; public class Solver { private boolean isSolve = false; private int move = -1; private class SearchNode implements Comparable<SearchNode>{ private final Board board; private final int move; private final int priority; private final SearchNode parent; private final boolean isTwin; public SearchNode(Board board, int move, SearchNode parent, boolean isTwin){ this.board = board; this.move = move; this.priority = board.manhattan() + move; this.parent = parent; this.isTwin = isTwin; } @Override public int compareTo(SearchNode that) { if (this.board.equals(that.board)) return 0; if (this.priority < that.priority) return -1; else return 1; } } private MinPQ<SearchNode> minPQ = new MinPQ<SearchNode>(new Comparator<SearchNode>() { public int compare(SearchNode o1, SearchNode o2) { if (o1.priority < o2.priority) return -1; else if (o1.priority == o2.priority) return 0; else return 1; } }); private Stack<Board> solutionQueue = new Stack<Board>(); // find a solution to the initial board (using the A* algorithm) public Solver(Board initial){ Board initialTwin = initial.twin(); SearchNode initSearchNode = new SearchNode(initial, 0, null, false); SearchNode initSearchNodeTwin = new SearchNode(initialTwin, 0, null, true); minPQ.insert(initSearchNode); minPQ.insert(initSearchNodeTwin); solve(); } private void solve(){ while(true){ //solve for original SearchNode searchNode = minPQ.delMin(); if (searchNode.board.isGoal()){ if (searchNode.isTwin){ this.isSolve = false; this.move = -1; } else { this.isSolve = true; this.move = searchNode.move; this.solutionQueue.push(searchNode.board); while(searchNode.parent != null){ searchNode = searchNode.parent; this.solutionQueue.push(searchNode.board); } } break; }else{ for (Board neiborBoard: searchNode.board.neighbors()){ SearchNode neiborNode = new SearchNode(neiborBoard, searchNode.move+1, searchNode, searchNode.isTwin); if (searchNode.parent == null){ minPQ.insert(neiborNode); } else if (!searchNode.parent.board.equals(neiborNode.board)){ minPQ.insert(neiborNode); } } } } } // is the initial board solvable? public boolean isSolvable(){ return this.isSolve; } // min number of moves to solve initial board; -1 if no solution public int moves(){ return this.move; } // sequence of boards in a shortest solution; null if no solution public Iterable<Board> solution(){ if (this.isSolve){ return this.solutionQueue; }else{ return null; } } public static void main(String[] args) { // create initial board from file In in = new In(args[0]); int N = in.readInt(); int[][] blocks = new int ; for (int i = 0; i < N; i++) for (int j = 0; j < N; j++) blocks[i][j] = in.readInt(); Board initial = new Board(blocks); // solve the puzzle Solver solver = new Solver(initial); // print solution to standard output if (!solver.isSolvable()) StdOut.println("No solution possible"); else { StdOut.println("Minimum number of moves = " + solver.moves()); for (Board board : solver.solution()) StdOut.println(board); } } }
相关文章推荐
- 算法分析与设计课程作业第四周#1
- 第四周算法作业
- 普林斯顿算法课第五周作业
- 普林斯顿算法课第二周作业
- Coursera普林斯顿算法课第二次作业
- 算法课第四周作业 | Course Schedule
- 第四周算法概论作业——无向图的DFS算法
- 算法作业_8(2017.3.19第四周)
- Coursera普林斯顿算法课第三次作业
- 算法课程Leetcode作业第四周技术博客
- 算法第四周作业02
- 算法第四周作业
- 普林斯顿算法课第三周作业
- 第四周作业——无向图的DFS算法【改
- 普林斯顿算法课第一周作业
- 第四周作业--1图的表示,2无向图的DFS算法,3有向图找环;
- 第四周作业--1图的表示,2无向图的DFS算法,3有向图找环;
- 程序设计入门—Java语言 . 翁恺-第四周编程作业-2.念整数
- 第四周作业(1,2)——高级编程技术
- 第四周作业