Princeton Algorithm Part 1 Week 4 - 8puzzle

有点难啊。。
85/100,memory测试全挂。。
总结稍后补上

Board.java

import java.util.Arrays;
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.MinPQ;
import edu.princeton.cs.algs4.StdOut;
import java.util.Comparator;

public class Board  {
    private int n; // board dimension n
    private int[] board; 
    private int zero; //position of zero
    
    public Board (int[][] blocks){
    // construct a board from an n-by-n array of blocks
    // (where blocks[i][j] = block in row i, column j)
        n = blocks.length;

        board = new int[n*n];
        int i = 0;
        for (int[] a : blocks){
            for (int b:a){
                if (b == 0) 
                    zero = i;
                board[i++] = b; // Assign value to board.
            }
        }
    }
    
    private int[][] decode (int[] board){
        int count = 0;
        int[][] result = new int[n][n];
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                result[i][j] = board[count++];
        return result;
    }
    
    private int row(int index){
        return index / n + 1;
    }
    
    private int col(int index){
        return index % n + 1;
    }
    
    public int dimension(){
        return n;
    }
    
    public int hamming(){
        int count = 0;
        for (int i = 0; i < n*n-1; i++){
            if (board[i] != i+1)
                count++;
        }       
        return count;
    }
    
    public int manhattan(){
        // sum of Manhattan distances between blocks and goal
        int manha = 0;
        int diff;
        for (int i = 0; i < n*n; i++){
            //bad move
            if(board[i] == 0)       diff = 0;
            else{
                diff = (Math.abs(row(i) - row(board[i]-1)) 
                      + Math.abs(col(i) - col(board[i]-1)));
            }
            manha += diff;}
        return manha;
    }
    
    public boolean isGoal(){
        // test the board is the goal board or not
        for (int i = 0; i < n*n-1 ; i++)
            if (board[i] != i+1)
                return false;
        return true;
    }
    
    public Board twin(){
        // return a board that is obtained by exch an pair of blocks;  
        //**Detecting unsolvable puzzles
        int[] twin1d = board.clone();
        int[][] twin2d = new int[n][n];
        if (twin1d[0] != 0 && twin1d[1] != 0 ){
            int temp = twin1d[0];
            twin1d[0] = twin1d[1];
            twin1d[1] = temp;
        }
        else {
            int temp = twin1d[2];
            twin1d[2] = twin1d[3];
            twin1d[3] = temp;
        }
        
        int c = 0;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                twin2d[i][j] = twin1d[c++];
        
        return new Board(twin2d);
    }
    
    public boolean equals(Object y){
        // does this board equal y  ?
        if (y == null)                          return false;
        if (y == this)                          return true;
        if (y.getClass() != this.getClass())    return false;

        Board thatB = (Board)y;
        if (thatB.dimension() != n)             return false;

        return Arrays.equals(this.board, thatB.board);
    }
    
    private void exch(int a, int b){
        int temp = board[a];
        board[a] = board[b];
        board[b] = temp;
    }

    public Iterable<Board> neighbors()  {
        // all neighboring boards
        // wtf?
        MinPQ<Board> pq = new MinPQ<Board>(new Comparator<Board>() {  
            public int compare(Board B1, Board B2) {  
               if (B1.manhattan() < B2.manhattan()) return -1;  
               if (B1.manhattan() == B2.manhattan()) return 0;  
               return 1;  
            }  
        });
        Board temp;
        if (row(zero) != n){

            temp = new Board(decode(board));
            temp.exch(zero,zero+n); //zero moves down;
            temp.zero = zero + n;
            pq.insert(temp);
        }
        if (row(zero) != 1){
            temp = new Board(decode(board));
            temp.exch(zero,zero-n); //zero moves up
            temp.zero = zero - n;
            pq.insert(temp);
        }
        if (col(zero) != 1){
            temp = new Board(decode(board));
            temp.exch(zero,zero-1); //zero moves left;
            temp.zero = zero - 1;
            pq.insert(temp);
        }
        if (col(zero) != n){
            temp = new Board(decode(board));
            temp.exch(zero,zero+1); //zero moves right;
            temp.zero = zero + 1;
            pq.insert(temp);
        }
        return pq;
    }
    

    public String toString(){
        // string representation of this board 
        StringBuilder sb = new StringBuilder();
        sb.append(n + "\n");
        
        for (int i = 0; i < n*n; i++){
            sb.append(" " + String.format("%2d", board[i]));
            if ( (i+1) % n == 0)
                sb.append("\n");
        }
        return sb.toString();
    }

    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[N][N];  
        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.hamming());  
        System.out.println("Initial!:");
        StdOut.println(initial);
        for(Board b : initial.neighbors())
            System.out.println(b);
    } 
}

Solver.java

import java.util.Comparator;
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.MinPQ;
import edu.princeton.cs.algs4.Stack;
import edu.princeton.cs.algs4.StdOut;


public class Solver {
    private int moves = -1; // when the board is unsolvable, moves = -1;
    private boolean solved = false;
    private Stack gameTree;
    private searchNode champion;
    private boolean isSolvable = false;
    private int step;
    
    //twin test;
    
    private MinPQ<searchNode> loserpool = new MinPQ <searchNode> (new Comparator<searchNode>(){
        public int compare(searchNode o1, searchNode o2){
            if (o1.priority < o2.priority) return -1;
            if (o1.priority == o2.priority) return 0;
            return 1;
        }
    });
    
    private class searchNode{
        private Board board;
        private int moves;
        private int priority;
        private searchNode prev;
        
        public searchNode(Board board, int moves, searchNode prev){
            this.board = board;
            this.moves = moves;
            this.prev = prev;
            this.priority = board.manhattan() + moves;  

        }
    }
    
    public Solver(Board initial){
        if(initial == null) throw new IllegalArgumentException();
        
        int TwinPriority = 2*initial.dimension(); // Starter Priority for Twin;
        
        Board twin = initial.twin();
        searchNode initialNode = new searchNode(initial, 0, null);
    //  searchNode twinNode = new searchNode(twin, 0, null); //twin test;  with lower priority
        searchNode twinNode = new searchNode(twin, TwinPriority, null);
        
        loserpool.insert (initialNode);
        loserpool.insert (twinNode);
        
        if(initialNode.board.isGoal())  
            championship(initialNode);
        
        if(twinNode.board.isGoal())     
            championship(twinNode);
            
        while(!solved)
            solve();
        
        gameTree(initialNode.board);
    }
    
    private void solve(){
        searchNode node = loserpool.delMin();

        step+=1;

        for (Board board: node.board.neighbors()){
            if (node.prev != null && board.equals(node.prev.board)){
            }else{
            searchNode child = new searchNode(board, node.moves+1, node);

            if(child.board.isGoal()) {
                championship(child);
                break;
            }
                
            loserpool.insert(child);
            }
        }
    }
    
    private void championship(searchNode champion){
        solved = true;
        this.champion = champion;
        this.moves = champion.moves;
    }
    
    public boolean isSolvable(){
        return isSolvable;
    }
    
    public int moves(){
        // min number of moves to solve initial board; -1 if unsolvable
        return moves;
    }
    
    private void SPrinter(){
        Stack<Board> S = gameTree;
        int move = 0;
        if(!isSolvable){
            System.out.println("It's unsolvable");
            return;
        }
        while (!S.isEmpty()){
            System.out.println("Move: " + move++ );
            System.out.println(S.pop());
        }
    }
    
    private  void gameTree(Board initial){
        Stack<Board> S = new Stack<Board>();
        searchNode node = champion;
        
        //test
        while(node.prev != null){
            S.push(node.board);
            node = node.prev;
        }
        S.push(node.board);
        
        //test
        /*for (int i = 0; i <= champion.moves; i++){
            S.push(node.board);
            node = node.prev;
        }*/
        this.gameTree = S;
        if(gameTree.peek() == initial)
            isSolvable = true;
        else this.moves = -1;
    }
    
    public Iterable<Board> solution(){
        // sequence of boards in a shortest solution; null if unsolvable
        if (isSolvable())
            return gameTree;
        return null;
    }
    
    public static void main(String[] args){
        // solve a slider puzzle (given below)
        
        In in = new In(args[0]);
        int n = in.readInt();
        int[][] blocks = new int[n][n];
        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);
        
        if(solver.isSolvable)  StdOut.println("Solvable");
        if(!solver.isSolvable)  StdOut.println("Unsolvable");
        System.out.println("Total move: " + solver.moves);
        // print solution
        System.out.println("---------------");
        solver.SPrinter();
        System.out.println(solver.isSolvable());
        System.out.println("Step: " + solver.step);
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,657评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,662评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,143评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,732评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,837评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,036评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,126评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,868评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,315评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,641评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,773评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,859评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,584评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,676评论 2 351

推荐阅读更多精彩内容