グリッド上のオブジェクトの可能な経路の数を見つけるために、BFSを使用して

MajesticButterfly:

私は、グリッドを表し、オブジェクトが移動することができ、すべての可能な場所を見つけるしたい行列を持っています。

オブジェクトは、水平方向または垂直方向に移動することができます。

のは、以下の例は、2D行列として表現され、私が探していたグリッドであると仮定しよう。オブジェクトが*で、0は、オブジェクトが移動できるよう、空の空間である、と1は、オブジェクトが飛び越えたりする上で行くことができない壁です。

それが唯一の水平方向または垂直方向に移動できるように提供されるこのオブジェクトのすべての可能な動きを見つけるための最善の方法は何ですか?

私が言ってメッセージ印刷したい:「オブジェクトはに行くことができる9つの場所がありますが」図9は、以下の例のためですが、私はそれがグリッドの下の任意の構成のために仕事をしたいと思います。私が持っているすべてを行うにはそうですが*の現在の座標を与えると、それは私にそれが移動することができます可能な位置の数を与えます。

ノートへの事は*の元の位置がメッセージ以下の例のために9とない10を印刷する理由である、計算では考慮されていないことです。

私は、細胞が壁であるかどう言われますisaWallメソッドを持っています。isaWall方法は、Cellクラスです。各セルは、その座標で表されます。私はBFSまたはDFSのようなアルゴリズムを使用してに見えたが、私はかなり私はアルゴリズムとあまり慣れていないよと、このケースでそれらを実装する方法を理解していませんでした。私は、グラフのノードとして細胞を使用するのではと思ったが、あまりにも確認してください、私はBFSとDFSのオンライン見た例から、あなたは通常、宛先ノードとソースノードを持っているでしょうので、グラフをトラバースする方法(ソースがされていませんでした*の位置)が、私は本当にこのような場合には、宛先ノードを持っていません。私は実際にいくつかの助けをいただければ幸いです。

00111110
01000010
100*1100
10001000
11111000

編集:私はコメントでお勧めされたウェブサイトをチェックして、私の独自のバージョンを実装しようとしました。これは、残念ながら動作しませんでした。私は、「フロンティア」を展開する必要があり、私は基本的にはJavaへの拡張コードを翻訳していることを理解し、それはまだ動作しません。ウェブサイトでは、プロセスを説明する続けますが、私の場合には、に行く全く先セルはありません。私は本当に例や私の場合に関する明確な説明をいただければと思います。

EDIT2:私はまだかなりそれによって混乱している、缶誰かが助けを喜ば?

dominicm00:

BFS / DFSは、一般的にされている間に使用開始と終了ポイント間の接続を見つけるために、それは彼らが何であるか本当にないです。BFS / DFSは、彼らが開始点から到達可能なすべての点を見つけるというのファンシーな方法です「グラフトラバーサルアルゴリズム」です。BFSあなたはどんな点を開始点からどれだけ離れているかを見つける必要があるときに使用され、DFSがときにだけ必要が使用されている:DFS(深さ優先探索は)私たちはあなたのニーズ(ノートがためにそれを使用しますので、実施することが容易ですすべてのポイントに移動します)。

私はあなたのデータが構成されている正確にどのように知りませんが、私は(簡単のため、私は開始セルを作ったマップは、整数の配列であると仮定して、いくつかの基本的な機能を定義します2):

Map.java

import java.awt.*;

public class Map {
    public final int width;
    public final int height;

    private final Cell[][] cells;
    private final Move[] moves;
    private Point startPoint;

    public Map(int[][] mapData) {
        this.width = mapData[0].length;
        this.height = mapData.length;

        cells = new Cell[height][width];
        // define valid movements
        moves = new Move[]{
            new Move(1, 0),
            new Move(-1, 0),
            new Move(0, 1),
            new Move(0, -1)
        };

        generateCells(mapData);
    }

    public Point getStartPoint() {
        return startPoint;
    }

    public void setStartPoint(Point p) {
        if (!isValidLocation(p)) throw new IllegalArgumentException("Invalid point");

        startPoint.setLocation(p);
    }

    public Cell getStartCell() {
        return getCellAtPoint(getStartPoint());
    }

    public Cell getCellAtPoint(Point p) {
        if (!isValidLocation(p)) throw new IllegalArgumentException("Invalid point");

        return cells[p.y][p.x];
    }

    private void generateCells(int[][] mapData) {
        boolean foundStart = false;
        for (int i = 0; i < mapData.length; i++) {
            for (int j = 0; j < mapData[i].length; j++) {
                /*
                0 = empty space
                1 = wall
                2 = starting point
                 */
                if (mapData[i][j] == 2) {
                    if (foundStart) throw new IllegalArgumentException("Cannot have more than one start position");

                    foundStart = true;
                    startPoint = new Point(j, i);
                } else if (mapData[i][j] != 0 && mapData[i][j] != 1) {
                    throw new IllegalArgumentException("Map input data must contain only 0, 1, 2");
                }
                cells[i][j] = new Cell(j, i, mapData[i][j] == 1);
            }
        }

        if (!foundStart) throw new IllegalArgumentException("No start point in map data");
        // Add all cells adjacencies based on up, down, left, right movement
        generateAdj();
    }

    private void generateAdj() {
        for (int i = 0; i < cells.length; i++) {
            for (int j = 0; j < cells[i].length; j++) {
                for (Move move : moves) {
                    Point p2 = new Point(j + move.getX(), i + move.getY());
                    if (isValidLocation(p2)) {
                        cells[i][j].addAdjCell(cells[p2.y][p2.x]);
                    }
                }
            }
        }
    }

    private boolean isValidLocation(Point p) {
        if (p == null) throw new IllegalArgumentException("Point cannot be null");

        return (p.x >= 0 && p.y >= 0) && (p.y < cells.length && p.x < cells[p.y].length);
    }

    private class Move {
        private int x;
        private int y;

        public Move(int x, int y) {
            this.x = x;
            this.y = y;
        }

        public int getX() {
            return x;
        }

        public int getY() {
            return y;
        }
    }
}

Cell.java

import java.util.LinkedList;

public class Cell {
    public final int x;
    public final int y;
    public final boolean isWall;
    private final LinkedList<Cell> adjCells;

    public Cell(int x, int y, boolean isWall) {
        if (x < 0 || y < 0) throw new IllegalArgumentException("x, y must be greater than 0");

        this.x = x;
        this.y = y;
        this.isWall = isWall;

        adjCells = new LinkedList<>();
    }

    public void addAdjCell(Cell c) {
        if (c == null) throw new IllegalArgumentException("Cell cannot be null");

        adjCells.add(c);
    }

    public LinkedList<Cell> getAdjCells() {
        return adjCells;
    }
}

今私達のDFS機能を書き込みます。A DFSは、再帰的にすべての到達可能なセルに触れた後、以下の手順で:

  1. 訪問したように、現在のセルをマーク
  2. 各隣接セルをループ
  3. セルは、すでにそのセルは、DFSを訪問し、現在の集計にそのセルに隣接するセルの数を追加されていない場合
  4. 現在のセル+ 1に隣接セルの数を返します

あなたはこのの可視化を見ることができますここで我々はすでに書いたすべてのヘルパー機能で、これは非常に単純です:

MapHelper.java

class MapHelper {
    public static int countReachableCells(Map map) {
        if (map == null) throw new IllegalArgumentException("Arguments cannot be null");
        boolean[][] visited = new boolean[map.height][map.width];

        // subtract one to exclude starting point
        return dfs(map.getStartCell(), visited) - 1;
    }

    private static int dfs(Cell currentCell, boolean[][] visited) {
        visited[currentCell.y][currentCell.x] = true;
        int touchedCells = 0;

        for (Cell adjCell : currentCell.getAdjCells()) {
            if (!adjCell.isWall && !visited[adjCell.y][adjCell.x]) {
                touchedCells += dfs(adjCell, visited);
            }
        }

        return ++touchedCells;
    }
}

以上です!あなたは、コードについての説明が必要な場合は、私に教えてください。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=210947&siteId=1