2012-04-11 26 views
8

Những gì tôi đang cố gắng làm là đếm số lần di chuyển để đạt được mục tiêu bằng đường đi ngắn nhất. Nó phải được thực hiện bằng cách sử dụng tìm kiếm đầu tiên. Tôi đặt lưới 8x8 vào một mảng 2d được lấp đầy với một trong bốn ký tự, E cho trống (có thể di chuyển vào những điểm này), B cho bị chặn (không thể di chuyển ở đây), R cho robot (điểm bắt đầu), hoặc G cho mục tiêu. Các thuật toán đã phải kiểm tra không gian di chuyển theo thứ tự lên, trái, phải, sau đó xuống, mà tôi tin rằng tôi đã làm một cách chính xác. Sau khi một nút được chọn, nó sẽ thay đổi nội dung của nó thành 'B'. Nếu không đạt được mục tiêu, 0 phải được trả lại.Tìm kiếm theo chiều rộng đầu tiên trên lưới 8x8 trong Java

Tôi đã thay đổi mã của mình để thực hiện những gì Kshitij nói với tôi và nó hoạt động rất đẹp. Tôi đã quá mệt mỏi khi thấy rằng tôi đã không khởi tạo hàng đợi của mình sau mỗi tập dữ liệu mới lol. Cảm ơn đã giúp đỡ!

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; 
} 

Trả lời

13

Bạn cần lưu 2 thứ trong hàng đợi của mình. Hãy gọi mỗi mục trong hàng đợi của bạn một nút.

  1. vị trí (mà bạn đã lưu trữ)
  2. count (di chuyển cần thiết để có được vị trí này từ vị trí bắt đầu)

Bạn bắt đầu bằng cách gán tính của vị trí bắt đầu của bạn để 0.

cách các thuật toán công trình là:

  1. bạn bật một nút từ hàng đợi
  2. bạn xác định nơi bạn có thể đi từ vị trí được chỉ định bởi nút bạn vừa mới xuất hiện. Tức là, nếu bạn coi điều này là "làm cây đang bay", bạn đang xác định con của nút bạn đã xuất hiện từ hàng đợi
  3. bạn thêm những trẻ này vào hàng đợi.

Trong bước thứ ba, khi bạn thêm nút con vào hàng đợi, bạn phải xác định số cần được thêm vào nút này. Số này chỉ đơn giản là số count of the parent node (that you popped in step 1) + 1

Cuối cùng, giá trị trả lại của bạn sẽ là số được kết hợp với nút mang vị trí đích. Ví dụ:

Ví dụ: cho phép làm việc với lưới 4x4, vị trí [0,0] là điểm bắt đầu và vị trí [0,3] là đích.

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

Ban đầu, hàng đợi của bạn sẽ là:

[{(0, 0), 0}] 

trong đó giá trị bên trong () là vị trí và giá trị thứ hai bên trong {} là đếm.

Bạn bật nút này từ hàng đợi của mình và bạn xác định rằng bạn có thể đến vị trí (0,1) và (1,0). Vì vậy, bạn thêm các mục {(0, 1), 1}{(1, 0), 1} vào hàng đợi. Lưu ý rằng số lượng là 1 vì số lượng của nút popped là 0 và chúng tôi tăng lên rằng bằng cách 1. hàng đợi của bạn bây giờ trông giống như:

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

Bạn bật phần tử đầu tiên, nhận ra rằng nó không có trẻ em khả thi, vì vậy bạn di chuyển trên.

Bạn bật phần tử còn lại và tìm ra rằng nó cung cấp cho bạn một nút bạn có thể truy cập, ở vị trí (2, 0). Vì nút bạn xuất hiện có số 1, bạn thêm vị trí mới này được ghép nối với count = 1 + 1 = 2 vào hàng đợi.

Cuối cùng, bạn sẽ bật nút mục tiêu từ hàng đợi của bạn, và nó đếm sẽ 9.

Sửa

Nếu bạn muốn nhận được đường đi từ nguồn đến đích, mã hóa hiện tại không hoạt động. Bạn cần duy trì một mảng 2D có kích thước 8x8 riêng biệt với số lượng thay vì mã hóa chúng trong chính nút đó. Và khi bạn cuối cùng tìm thấy số đếm cho đích, bạn quay trở lại từ đích đến nguồn bằng cách sử dụng mảng đếm 2D. Về cơ bản, nếu bạn có thể đến đích trong 9 lần di chuyển, bạn có thể tới một trong các vị trí liền kề của nó trong 8 lần di chuyển. Vì vậy, bạn tìm thấy vị trí đã đếm 8 và tiếp giáp với điểm đến. Bạn lặp lại lặp lại điều này cho đến khi bạn đến nguồn.

Phương pháp bạn mô tả, nơi bạn thêm phần tử phụ vào các nút không hoạt động. Tôi sẽ để nó cho bạn tìm hiểu lý do vì đây là bài tập về nhà :)

+0

Dường như vn, cảm ơn vì sự thấu hiểu. Tôi cho rằng việc in các đường dẫn khả thi sẽ hoạt động theo cùng một cách, bằng cách chỉ thêm hướng được di chuyển như một giá trị trong hàng đợi. Vì vậy, sau khi popping (1,0) hàng đợi sẽ trông như thế này: {(0,2), 2, R}. Về bản chất, điều này sẽ cho phép tôi in đường dẫn khi đạt được mục tiêu, đúng không? – Ethan

+0

Tôi sẽ chỉnh sửa câu trả lời của mình để trả lời rằng –

+0

@KshitijMehta điều gì sẽ xảy ra với phần tử xếp hàng {(0, 1), 1} khi không có childeren khả thi ... khi nào bạn bật nó HOẶC nó vẫn còn trong hàng đợi? –

0

Đây là một cách thay thế ngắn ngắn thay thế cho mã của bạn. Chính xác cùng một ý tưởng nhưng không cần quá nhiều điều kiện nếu bạn kiểm tra tính hợp lệ của mỗi tọa độ. Tất cả điều này có thể được thực hiện trong một lần. Có một cái nhìn.

Tôi đã nhận xét giải thích nhiều nhất có thể. Nó có thể đọc được ngay cả đối với những người không có ý tưởng nhỏ. Tôi tình cờ gặp câu hỏi của bạn khi tôi đang thực hiện một giải pháp cho một vấn đề tương tự (giống nhau), nơi một anh chàng bị mắc kẹt trong mê cung phải tìm đường ra. Có các bẫy (B) và các khu vực di chuyển (E) trong lưới. Mục đích là để đạt được điểm đến của mình (G).

Dù sao, đây là mã tổng quát. Tôi lấy trong không có hàng, cột và sau đó là lưới hoàn chỉnh. Tôi chỉ in cho dù có thể đạt được điểm đến hay không. Tôi rời khỏi phần còn lại tối đa một người đang đọc này như một bài tập để chắc chắn rằng bạn đã hiểu mã;)

tâm sự thật rằng chính khách quan của câu trả lời của tôi là để cho bạn thấy rằng các kích thước của BFS của bạn chức năng có thể được giảm. Tôi đang đăng toàn bộ giải pháp của mình chỉ để đưa ra ý tưởng tổng thể về BFS được áp dụng trong một lưới kể từ khi tôi vật lộn trong khi học nó. Hy vọng rằng, điều này sẽ giúp đỡ một người nào đó bị mắc kẹt trong tình huống tương tự. Nếu bạn muốn các postion hoặc con đường theo sau hoặc bất cứ điều gì, hãy làm theo các hướng dẫn từ các câu trả lời trong câu hỏi này. Do đó cho mình;)

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 
     } 
    } 
} 

Mã trong hành động: http://ideone.com/jiZKzn

Bất kỳ lời đề nghị hoan nghênh nhất. Chúc mừng: D

Các vấn đề liên quan