Sim's blog

電子工作はじめてみました

最短迷路問題のJavaコード

2010-01-13 23:51:12 | その他
人材獲得作戦・4 試験問題ほか」という記事で取り上げられている迷路の最短経路を求める問題をJavaで解いてみました。
ファイル入出力以外は、ほとんどCで書いても変わらないようなコードです。
一応、検索しないで1時間くらいでした。
import java.io.File;
import java.util.Scanner;


public class Maze {

    public static void main(String[] args) throws Exception {
        new Maze().run();
    }

    final int MAXSIZE = 128 * 128;
    final int START = 0;
    final int WALL  = -1;
    final int BLANK = -2;
    final int GOAL  = -3;
    final int ROUTE = -4;

    final boolean AnswerType = true; // falseで全解出力

    int[] ban = new int[MAXSIZE];
    int[] answer = new int[MAXSIZE];
    int xsize;
    int ysize;
    int bansize;
    int startpos;
    int goalpos;

    void run() throws Exception{
        read("maze.txt");
        solve();
    }

    void read(String filename) throws Exception {
        Scanner scan = new Scanner(new File(filename));
        String s;
        int i, p;

        // 配列オーバーフローとかはチェックしない
        p = 0;
        for(ysize = 0; scan.hasNext(); ysize++){
            s = scan.nextLine();
            for(i = 0; i < s.length(); i++){
                switch(s.charAt(i)){
                case '*' : ban[p] = WALL;  break;
                case ' ' : ban[p] = BLANK; break;
                case 'S' : ban[p] = START; startpos = p; break;
                case 'G' : ban[p] = GOAL;  goalpos  = p; break;
                }
                p++;
            }
            xsize = i;
        }
        bansize = xsize * ysize;
    }

    void solve(){
        for(int i = 0; i < bansize; i++) answer[i] = ban[i];

        // mark
        int level = mark();

        // 戻り道を探す
        search(goalpos, level);
    }

    int mark(){
        int p;
        int level;
        for(level = 0; ; level++){
            for(p = 0; p < bansize; p++){
                if(ban[p] == level){
                    // 枠のチェックなし、というかここはキューに積む方がいい。
                    if(ban[p - 1] == BLANK) ban[p - 1] = level + 1;
                    if(ban[p + 1] == BLANK) ban[p + 1] = level + 1;
                    if(ban[p - xsize] == BLANK) ban[p - xsize] = level + 1;
                    if(ban[p + xsize] == BLANK) ban[p + xsize] = level + 1;
                    if(ban[p - 1] == GOAL || ban[p + 1] == GOAL || ban[p - xsize] == GOAL || ban[p + xsize] == GOAL){
                        return level;
                    }
                }
            }
        }
    }

    boolean check(int p, int level){
        if(ban[p] == level){
            answer[p] = ROUTE;
            if(search(p, level - 1)) return true;
            answer[p] = BLANK;
        }
        return false;
    }

    boolean search(int p, int level){
        if(level == 0){
            disp(answer);
            return AnswerType;
        }
        if(check(p - 1, level)) return true;
        if(check(p + 1, level)) return true;
        if(check(p - xsize, level)) return true;
        if(check(p + xsize, level)) return true;
        return false;
    }

    void disp(int[] ban){
        int x, y, p;
        p = 0;
        for(y = 0; y < ysize; y++){
            for(x = 0; x < xsize; x++){
                switch(ban[p]){
                case WALL  : System.out.printf("*"); break;
                case BLANK : System.out.printf(" "); break;
                case START : System.out.printf("S"); break;
                case GOAL  : System.out.printf("G"); break;
                default    : System.out.printf("$"); break;
                }
                p++;
            }
            System.out.printf("\n");
        }
    }
}


最新の画像もっと見る

2 コメント

コメント日が  古い順  |   新しい順
Unknown (watanabe8760)
2010-04-10 12:50:34
5時間かかりました。。。
http://trwtnb.blogspot.com/2010/04/java.html
返信する
re:Unknown (Sim)
2010-04-13 02:38:36
こんにちは、watanabe8760さん
おつかれさまでした。私は以前、直接最短経路問題というわけではなかったのですが、似たような問題にぶちあたって自分で解決したことがあって、そのときの経験があったのでさくさくできましたが、全くのはじめてだとつらそうです。なんにせよ、プログラミングは経験というか引き出しが多いと後々役に立つことが多いみたいです。
返信する

コメントを投稿