10

私がやろうとしているのは、最短経路を使用してゴールに到達するまでに何回移動する必要があるかを数えることです。これは、幅優先検索を使用して行う必要があります。8x8 グリッドを 2 次元配列に入れ、4 つの文字のいずれかで満たされます。E は空 (これらのスポットに移動できます)、B はブロック (ここでは移動できません)、R はロボット (開始点)、または G です。ゴールのために。アルゴリズムは、可動スペースを上、左、右、下の順にチェックする必要がありましたが、これは正しく行ったと思います。ノードがチェックされると、その内容が「B」に変わります。目標に到達できない場合は、0 を返す必要があります。

Kshitij が私に言ったことを実装するためにコードを変更しました。新しいデータ セットが作成されるたびに、キューを初期化していないことに気がつきませんでした (笑)。助けてくれてありがとう!

public static int bfSearch(){
    Queue <int []> queue = new LinkedList <int []> ();
    int [] start = {roboty,robotx,0};
    queue.add(start);

    while (queue.peek() != null){
        int [] array = queue.remove();

            if(array[0]-1 >= 0 && grid[array[0]-1][array[1]] != 'B'){

                if (grid[array[0]-1][array[1]] == 'G'){
                    return array[2]+1; 
                }
                else{
                    grid[array[0]-1][array[1]] = 'B';
                    int [] temp = {array[0]-1, array[1], array[2]+1};
                    queue.add(temp);
                }
            }

            if(array[1]-1 >= 0 && grid[array[0]][array[1]-1] != 'B'){

                if (grid[array[0]][array[1]-1] == 'G'){
                    return array[2]+1;
                }
                else{
                    grid[array[0]][array[1]-1] = 'B';
                    int [] temp = {array[0], array[1]-1, array[2]+1};
                    queue.add(temp);
                }
            }

            if(array[1]+1 <= 7 && grid[array[0]][array[1]+1] != 'B'){

                if (grid[array[0]][array[1]+1] == 'G'){
                    return array[2]+1;
                }
                else{
                    grid[array[0]][array[1]+1] = 'B';
                    int [] temp = {array[0], array[1]+1, array[2]+1};
                    queue.add(temp);
                }
            }

            if(array[0]+1 <= 7 && grid[array[0]+1][array[1]] != 'B'){

                if (grid[array[0]+1][array[1]] == 'G'){
                    return array[2]+1;
                }
                else{
                    grid[array[0]+1][array[1]] = 'B';
                    int [] temp = {array[0]+1, array[1], array[2]+1};
                    queue.add(temp);
                }
            }
        }           
    return 0;
}
4

2 に答える 2

16

キューに 2 つのものを保存する必要があります。キュー内の各アイテムをノードと呼びましょう。

  1. 位置(すでに保存している)
  2. count (開始位置からこの位置に到達するために必要な移動)

開始位置のカウントを 0 に割り当てることから始めます。

アルゴリズムの仕組みは次のとおりです。

  1. キューからノードをポップします
  2. ポップしたばかりのノードによって指定された位置から移動できる場所を決定します。つまり、これを「その場でツリーを作成する」と見なすと、キューからポップしたノードの子を決定していることになります。
  3. これらの子をキューに追加します。

3 番目のステップで、ノードの子をキューに追加するときに、このノードに追加する必要がある数を決定する必要があります。このカウントは単にcount of the parent node (that you popped in step 1) + 1

最後に、戻り値は、目的の位置を運ぶノードに関連付けられたカウントになります。

たとえば、位置 [0,0] が開始点、位置 [0,3] が目的地である 4x4 グリッドで作業してみましょう。

S E E B
E B E E
B B B E
G E E E

最初は、キューは次のようになります。

[{(0, 0), 0}]

内の値()は位置で、内の 2 番目の値{}はカウントです。

このノードをキューからポップし、位置 (0,1) と (1,0) に到達できると判断します。そのため、アイテム{(0, 1), 1}{(1, 0), 1}キューに追加します。ポップされたノードのカウントが 0 だったので、カウントが 1 であることに注意してください。これを 1 ずつインクリメントしました。キューは次のようになります。

[{(0, 1), 1},  {(1, 0), 1}]

最初の要素をポップし、実行可能な子がないことに気付き、先に進みます。

残りの要素をポップすると、位置 (2, 0) にアクセスできる 1 つのノードが得られることがわかります。ポップしたノードのカウントは 1 であるため、この新しい位置をカウント = 1 + 1 = 2 とペアにしてキューに追加します。

最終的に、ゴール ノードをキューからポップすると、カウントは 9 になります。

編集

ソースから宛先へのパスを取得する場合、現在のエンコーディングはそのままでは機能しません。ノード自体でそれらをエンコードするのではなく、カウントを含むサイズ 8x8 の別の 2D 配列を維持する必要があります。最終的に宛先のカウントが見つかったら、2D カウント配列を使用して宛先からソースにバックトラックします。基本的に、9手で目的地に到達できる場合、隣接する位置の1つに8手で到達できます。したがって、カウント 8 を持ち、目的地に隣接する位置を見つけます。ソースに到達するまで、これを繰り返します。

ノードに余分な要素を追加する、説明した方法は機能しません。これは宿題なので、理由はあなたに任せます:)

于 2012-04-11T03:24:52.573 に答える
0

これは、コードの短い代替案です。まったく同じ考え方ですが、各座標の有効性をチェックする非常に多くの「if」条件は必要ありません。これはすべて一度に行うことができます。見てください。

できる限り説明をコメントしました。知識のない人でも読めます。迷路に閉じ込められた男が自分の道を見つけなければならないという同様の(同じ?)問題の解決策を実装していたときに、たまたまあなたの質問に出くわしました。グリッドにはトラップ (B) と可動領域 (E) がありました。目標は、目的地 (G) に到達することでした。

とにかく、ここに一般化されたコードがあります。行数、列数、そして完全なグリッドを取り込みます。目的地に到達できるかどうかだけを出力しています。残りは、あなたがコードを理解していることを確認するための演習としてこれを読んでいる誰かに任せます ;)

私の回答の主な目的は、BFS 関数のサイズを縮小できることを示すことです。学習中に苦労したため、グリッドに適用される BFS の全体的なアイデアを提供するためだけに、ソリューション全体を投稿しています。うまくいけば、これは誰かが同じ状況で立ち往生するのを助けるでしょう. 位置やたどるパスなどが必要な場合は、この質問の回答の指示に従ってください。自分でやれ ;)

import java.util.*;

/**
 * Created by Shreyans on 4/30/2015 at 10:27 PM using IntelliJ IDEA
 */

class MAZE
{
    static int r,c,s1,s2,f1,f2;//Rows, Columns, Start Coordinates, Finish Coordinates
    static int[] dx={1,-1,0,0};//right, left, NA, NA
    static int[] dy={0,0,1,-1};//NA, NA, bottom, top
    static char[][] grid;//Main grid
    public static void main(String[] args)
    {
        Scanner sc=new Scanner(System.in);//I suggest using faster IO if you have performance concerns. I did. Scanner is readable hence the choice
        r=sc.nextInt();
        c=sc.nextInt();
        grid=new char[r][c];
        for(int i=0;i<r;i++)
        {
            char[] s1=sc.next().toCharArray();//Reading a line of the Grid
            System.arraycopy(s1,0,grid[i],0,c);//Nice inbuilt function to copy contents of an array. Also doable manually
        }
        s1=sc.nextInt()-1;
        s2=sc.nextInt()-1;
        f1=sc.nextInt()-1;
        f2=sc.nextInt()-1;
        if(MAZEBFS())
        {
            System.out.println("PATH EXISTS");
        }
        else
        {
            System.out.println("PATH DOES NOT EXIST");
        }
    }
    private static boolean MAZEBFS()
    {
        if(s1==f1&&s2==f2)
        {
            return true;//He's already there
        }
        else
        {
            grid [f1][f2]='G';//finish
            Queue<int[]> q=new LinkedList<int[]>();
            int[]start={s1,s2};//Start Coordinates
            q.add(start);//Adding start to the queue since we're already visiting it
            grid[s1][s2]='B';
            while(q.peek()!=null)
            {
                int[]curr=q.poll();//poll or remove. Same thing
                for(int i=0;i<4;i++)//for each direction
                {
                    if((curr[0]+dx[i]>=0&&curr[0]+dx[i]<r)&&(curr[1]+dy[i]>=0&&curr[1]+dy[i]<c))
                    {
                        //Checked if x and y are correct. ALL IN 1 GO
                        int xc=curr[0]+dx[i];//Setting current x coordinate
                        int yc=curr[1]+dy[i];//Setting current y coordinate
                        if(grid[xc][yc]=='G')//Destination found
                        {
                            //System.out.println(xc+" "+yc);
                            return true;
                        }
                        else if(grid[xc][yc]=='E')//Movable. Can't return here again so setting it to 'B' now
                        {
                            //System.out.println(xc+" "+yc);
                            grid[xc][yc]='B';//now BLOCKED
                            int[]temp={xc,yc};
                            q.add(temp);//Adding current coordinates to the queue
                        }
                    }
                }
            }
            return false;//Will return false if no route possible
        }
    }
}

実際のコード: http://ideone.com/jiZKzn

どんな提案でも大歓迎です。乾杯 :D

于 2015-05-01T12:18:53.457 に答える