算法导论第四版学习——习题四8 Puzzle

题目正文:

http://coursera.cs.princeton.edu/algs4/assignments/8puzzle.html

作业难点:

1、如何验证Puzzle是否可解?题目中有提示,如果相邻两个格子交换后得到的“Twin Puzzle”进行求解,如果Twin有解那么原始Puzzle就无解。

作业技巧:

1、checklist提到把Twin Puzzle和Puzzle放在一个Priority Queue中,其实就是在设计自己的Node数据结构的时候加一个boolean类型标识是否twin就好了

2、别忘了Equal的实现要素,首先是否为空、其次是否类型一致、再其次维度是否一致、最后逐个比较。

代码参考:

(这是我自己亲测100分的答案,不代表写得最好,请在自己实在完成不了的时候再看,不然的话做这个题目的意义一点都没有)

  1 import edu.princeton.cs.algs4.In;
  2 import edu.princeton.cs.algs4.StdOut;
  3
  4 import java.util.Stack;
  5
  6
  7 public class Board {
  8     private int ngrid;
  9     private char[] board;
 10     private int hammingCache;
 11     private int manhattanCache;
 12
 13     public Board(int[][] blocks) {
 14         ngrid = blocks.length;
 15
 16         if (ngrid < 2) {
 17             throw new NullPointerException();
 18         }
 19
 20         board = new char[ngrid * ngrid];
 21         hammingCache = 0;
 22         manhattanCache = 0;
 23
 24         for (int i = 0; i < ngrid; i++) {
 25             for (int j = 0; j < ngrid; j++) {
 26                 int currentValue = blocks[i][j];
 27                 board[(i * ngrid) + j] = (char) currentValue;
 28
 29                 if (currentValue != 0) {
 30                     if (currentValue != ((i * ngrid) + j + 1)) {
 31                         hammingCache++;
 32                     }
 33
 34                     int col = (currentValue - 1) % ngrid;
 35                     int row = (currentValue - col - 1) / ngrid;
 36                     // StdOut.println("v:"+currentValue+"r:"+row+"c:"+col);
 37                     manhattanCache += (((col > j) ? (col - j) : (j - col)) +
 38                     ((row > i) ? (row - i) : (i - row)));
 39                 }
 40             }
 41         }
 42     }
 43
 44     public int dimension() // board dimension n
 45      {
 46         return ngrid;
 47     }
 48
 49     public int hamming() // number of blocks out of place
 50      {
 51         return hammingCache;
 52     }
 53
 54     public int manhattan() // sum of Manhattan distances between blocks and goal
 55      {
 56         return manhattanCache;
 57     }
 58
 59     public boolean isGoal() // is this board the goal board?
 60      {
 61         return hammingCache == 0;
 62     }
 63
 64     public Board twin() // a board that is obtained by exchanging any pair of blocks
 65      {
 66         int[][] twin = new int[ngrid][ngrid];
 67
 68         for (int i = 0; i < ngrid; i++) {
 69             for (int j = 0; j < ngrid; j++) {
 70                 twin[i][j] = (int) board[(i * ngrid) + j];
 71             }
 72         }
 73
 74         if ((twin[0][0] == 0) || (twin[0][1] == 0)) {
 75             swap(twin, 1, 0, 1, 1);
 76         } else {
 77             swap(twin, 0, 0, 0, 1);
 78         }
 79
 80         return new Board(twin);
 81     }
 82
 83     public boolean equals(Object y) // does this board equal y?
 84      {
 85         if (y == this) {
 86             return true;
 87         }
 88
 89         if (y == null) {
 90             return false;
 91         }
 92
 93         if (y.getClass() != this.getClass()) {
 94             return false;
 95         }
 96
 97         Board that = (Board) y;
 98         if (that.dimension() != ngrid) return false;
 99         for (int i = 0; i < (ngrid * ngrid); i++) {
100             if (this.board[i] != that.board[i]) {
101                 return false;
102             }
103         }
104
105         return true;
106     }
107
108     public Iterable<Board> neighbors() // all neighboring boards
109      {
110         int blankRow = 0;
111         int blankCol = 0;
112         Stack<Board> neighbours = new Stack<Board>();
113
114         int[][] clone = new int[ngrid][ngrid];
115
116         for (int i = 0; i < ngrid; i++) {
117             for (int j = 0; j < ngrid; j++) {
118                 clone[i][j] = (int) board[(i * ngrid) + j];
119
120                 if (clone[i][j] == 0) {
121                     blankRow = i;
122                     blankCol = j;
123                 }
124             }
125         }
126
127         if (blankCol != 0) {
128             swap(clone, blankRow, blankCol - 1, blankRow, blankCol);
129             neighbours.push(new Board(clone));
130             swap(clone, blankRow, blankCol - 1, blankRow, blankCol);
131         }
132
133         if (blankCol != (ngrid - 1)) {
134             swap(clone, blankRow, blankCol + 1, blankRow, blankCol);
135             neighbours.push(new Board(clone));
136             swap(clone, blankRow, blankCol + 1, blankRow, blankCol);
137         }
138
139         if (blankRow != 0) {
140             swap(clone, blankRow - 1, blankCol, blankRow, blankCol);
141             neighbours.push(new Board(clone));
142             swap(clone, blankRow - 1, blankCol, blankRow, blankCol);
143         }
144
145         if (blankRow != (ngrid - 1)) {
146             swap(clone, blankRow + 1, blankCol, blankRow, blankCol);
147             neighbours.push(new Board(clone));
148         }
149
150         return neighbours;
151     }
152
153     private void swap(int[][] array, int i, int j, int a, int b) {
154         int temp = array[i][j];
155         array[i][j] = array[a][b];
156         array[a][b] = temp;
157     }
158
159     public String toString() // string representation of this board (in the output format specified below)
160      {
161         StringBuilder s = new StringBuilder();
162         s.append(ngrid + "\n");
163         for (int i = 0; i < ngrid; i++) {
164             for (int j = 0; j < ngrid; j++) {
165                 s.append(String.format("%2d ", (int) board[(i * ngrid) + j]));
166             }
167
168             s.append("\n");
169         }
170
171         return s.toString();
172     }
173
174     public static void main(String[] args) // unit tests (not graded)
175      {
176         // read in the board specified in the filename
177         In in = new In(args[0]);
178         int n = in.readInt();
179         int[][] tiles = new int[n][n];
180
181         for (int i = 0; i < n; i++) {
182             for (int j = 0; j < n; j++) {
183                 tiles[i][j] = in.readInt();
184             }
185         }
186
187         // solve the slider puzzle
188         Board initial = new Board(tiles);
189         StdOut.printf("hamming:%d manhattan:%d \n", initial.hamming(),
190             initial.manhattan());
191         StdOut.println("dim:" + initial.dimension());
192         StdOut.println(initial.toString());
193         StdOut.println("goal:" + initial.isGoal());
194         StdOut.println("twin:\n" + initial.twin().toString());
195
196         StdOut.println("neighbours:");
197
198         for (Board s : initial.neighbors()) {
199             StdOut.println(s.toString());
200         }
201     }
202 }

Board

  1 import edu.princeton.cs.algs4.In;
  2 import edu.princeton.cs.algs4.MinPQ;
  3 import edu.princeton.cs.algs4.StdOut;
  4
  5 import java.util.Stack;
  6
  7
  8 public class Solver {
  9     private boolean solvable;
 10     private GameNode originLast;
 11
 12     public Solver(Board initial) // find a solution to the initial board (using the A* algorithm)
 13      {
 14         if (initial == null) {
 15             throw new NullPointerException();
 16         }
 17
 18         solvable = true;
 19
 20         MinPQ<GameNode> queue = new MinPQ<GameNode>();
 21
 22         queue.insert(new GameNode(initial, null, 0, false));
 23         queue.insert(new GameNode(initial.twin(), null, 0, true));
 24
 25         while (!queue.isEmpty()) {
 26             GameNode processed = queue.delMin();
 27
 28             if (!processed.isTwin) {
 29                 originLast = processed;
 30             }
 31
 32             if (processed.boardValue.isGoal()) {
 33                 if (processed.isTwin) {
 34                     solvable = false;
 35                 }
 36
 37                 break;
 38             }
 39
 40             for (Board neighbor : processed.boardValue.neighbors()) {
 41                 if ((processed.prev == null) ||
 42                         !processed.prev.boardValue.equals(neighbor)) {
 43                     queue.insert(new GameNode(neighbor, processed,
 44                             processed.moves + 1, processed.isTwin));
 45                 }
 46             }
 47         }
 48     }
 49
 50     public boolean isSolvable() // is the initial board solvable?
 51      {
 52         return solvable;
 53     }
 54
 55     public int moves() // min number of moves to solve initial board; -1 if unsolvable
 56      {
 57         if (isSolvable()) {
 58             return originLast.moves;
 59         } else {
 60             return -1;
 61         }
 62     }
 63
 64     public Iterable<Board> solution() // sequence of boards in a shortest solution; null if unsolvable
 65      {
 66         if (!isSolvable()) {
 67             return null;
 68         }
 69
 70         Stack<Board> solutions = new Stack<Board>();
 71         GameNode current = originLast;
 72
 73         while (current.prev != null) {
 74             solutions.push(current.boardValue);
 75             current = current.prev;
 76         }
 77
 78         solutions.push(current.boardValue);
 79
 80         Stack<Board> solutions2 = new Stack<Board>();
 81
 82         while (!solutions.empty()) {
 83             solutions2.push(solutions.pop());
 84         }
 85
 86         return solutions2;
 87     }
 88
 89     public static void main(String[] args) {
 90         // create initial board from file
 91         In in = new In(args[0]);
 92         int n = in.readInt();
 93         int[][] blocks = new int[n][n];
 94
 95         for (int i = 0; i < n; i++)
 96             for (int j = 0; j < n; j++)
 97                 blocks[i][j] = in.readInt();
 98
 99         Board initial = new Board(blocks);
100
101         // solve the puzzle
102         Solver solver = new Solver(initial);
103
104         // print solution to standard output
105         if (!solver.isSolvable()) {
106             StdOut.println("No solution possible");
107         } else {
108             StdOut.println("Minimum number of moves = " + solver.moves());
109
110             for (Board board : solver.solution())
111                 StdOut.println(board);
112         }
113     }
114
115     private class GameNode implements Comparable<GameNode> {
116         private Board boardValue;
117         private GameNode prev;
118         private int moves;
119         private boolean isTwin;
120
121         public GameNode(Board current, GameNode prev, int moves, boolean isTwin) {
122             this.boardValue = current;
123             this.prev = prev;
124             this.moves = moves;
125             this.isTwin = isTwin;
126         }
127
128         public int compareTo(GameNode that) {
129             int priority1 = this.boardValue.manhattan() + this.moves;
130             int priority2 = that.boardValue.manhattan() + that.moves;
131
132             if (priority1 == priority2) {
133                 return 0;
134             } else if (priority1 > priority2) {
135                 return 1;
136             } else {
137                 return -1;
138             }
139         }
140     }
141 }

Solver

时间: 2024-11-04 11:02:46

算法导论第四版学习——习题四8 Puzzle的相关文章

算法导论第四版学习——习题三Collinear Points

题目正文: http://coursera.cs.princeton.edu/algs4/assignments/collinear.html 作业难点: 1.仔细思考会感觉有很多实现方法,但是如果没有适当使用排序,算法时间复杂度就会轻易超过要求.(包括暴力算法) 2.隐含需要实现自己的数据结构用来组织“线”的集合,当然也可以用Stack或者Queue或者LinkedList,但是我个人是自己实现的. 3.由于一条线段只能出现一次,所以有一个去重的问题.(最难) 作业技巧: 1.基本按照题目的先

算法导论第四版学习——习题一Percolation

题目正文: http://coursera.cs.princeton.edu/algs4/assignments/percolation.html 作业难点: 1.backwash(倒灌)的判断,如果不使用另一个WeightedUnionFind对象,要在要求的时间和空间范围内实现是很困难的 和论坛里的学生一样,尝试只只使用上部的虚拟节点,下部判断联通使用循环+break,提交后不满足时间复杂度要求 你也可以不考虑backwash这种情况,因为backwash对连通性并没有直接影响 2.Unio

算法导论第四版学习——习题五Kd-Tree

题目正文: http://coursera.cs.princeton.edu/algs4/assignments/kdtree.html 作业难点: 如何组织自己的数据结构是本道题的最难点,基本上有思路就肯定可以完成.题目一定要看仔细,基本上2dtree部分已经把实现原理说清楚了. 作业技巧: 1.逐步实现,实现完成后用insert.contain测试下,没问题再写draw,测试没问题再写其余的. 2.重复输入的问题不要忘了 3.range虽然api里写的是all point inside th

算法导论第四版学习——习题二Deques and Randomized Queues

题目正文: http://coursera.cs.princeton.edu/algs4/assignments/queues.html 作业难点: 1.选择使用链表还是数组,将会是第一个问题,选择合适会减少很多工作量. 2.并行从RandomizedQueue中取两个枚举,这两个枚举必须是不一样的,所以有很多偷懒的“伪随机”是行不通的. 3.SubSet仅需K存储而不是N存储,即可实现.(这个我也没想到方法实现) 作业技巧: 1.可遍数组和邻接节点两种数据结构都已经给你了,你只要改改,基本上实

Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记四)之Operators

At the lowest level, data in Java is manipulated using operators Using Java Operators An operator takes one or more argument and produces a new value. The arguements are in a different form than ordinary method calls, but the effect is the same. + :

马克思主义基本原理概论》学生辅学读本(第四版)习题答案

马克思主义基本原理概论 学生辅学读本(第四版)习题答案 逄锦聚<马克思主义基本原理概论>学生辅学读本(第四版)习题答案?本书是马克思主义理论研究和建设工程重点教材<马克思主义基本原理概论>(2013年修订版)的配套用书,根据党的十八大精神,进行了相应内容的修改.本书依据教材的逻辑体系,从适合学生学习的角度出发进行内容设计,每章包括"明确学习目标"."教师导航分析"."观点案例点评"."游弋大千题海".&

计算机组成原理_第四版课后习题答案(完整版)

计算机组成原理_第四版课后习题答案(完整版) ?第一章 1.?比较数字计算机和模拟计算机的特点. 解:模拟计算机的特点:数值由连续量来表示,运算过程是连续的: 数字计算机的特点:数值由数字量(离散量)来表示,运算按位进行. 两者主要区别见P1?表1.1. 2.?数字计算机如何分类?分类的依据是什么? 解:分类: 数字计算机分为专用计算机和通用计算机.通用计算机又分为巨型机.大型机. 中型机.小型机.微型机和单片机六类. 分类依据:专用和通用是根据计算机的效率.速度.价格.运行的经济性和适应性来划

数学物理方法 高教 第四版 课后习题答案

数学物理方法 高等教育出版社 第四版 课后习题答案 课后习题答案下载地址 链接:https://pan.baidu.com/s/1KqePoJ8AXb4vAxXadOCfCg提取码:73um 如果链接失效扫一扫右侧,回复 数学物理方法答案 即可免费获取 百度文库所有文档原格式下载方法  回复 文库免费下载 数学物理方法 高教 第四版 课后习题答案 更多相关: 高等数学同济七版上册课后答案:https://www.cnblogs.com/need/p/11491277.html 高等数学同济七版下

算法导论 第三版 中文版

下载地址:网盘下载 算法导论 第三版 中文版 清晰 PDF,全书共8部分35章节,内容涵盖基础知识.排序和顺序统计量.数据结构.高级设计和分析技术.高级数据结构.图算法.算法问题选编.以及数学基础知识.非常实用的参考书和工程实践手册.此外,其他资源也已经上传,全部免费,欢迎大家下载! 第3版的主要变化 1.新增了van Emde Boas树和多线程算法,并且将矩阵基础移至附录. 2.修订了递归式(现在称为"分治策略")那一章的内容,更广泛地覆盖分治法. 3.移除两章很少讲授的内容:二项