Giải pháp mê cung xuống dốc


9

Một mê cung xuống dốc được đưa ra dưới dạng một loạt các hàng gồm các chữ số được phân tách từ 0 đến 9, cộng với một "S" và một "X", trong đó S biểu thị điểm bắt đầu và X biểu thị kết thúc. Trong mê cung xuống dốc, bạn chỉ có thể đi đến một không gian tiếp giáp với bạn ở phía bắc, nam, đông hoặc tây (không có đường chéo) và bạn chỉ có thể đi đến các không gian có giá trị nhỏ hơn hoặc bằng giá trị bạn hiện đang trên.

Chương trình sẽ xuất ra một đường dẫn để điều hướng qua mê cung có cùng định dạng với đầu vào, chỉ tất cả các không gian đi qua phải có dấu "." trong đó và tất cả các không gian không mong muốn nên có "#" trong đó. Các ô bắt đầu và kết thúc cũng phải giữ "S" và "X" tương ứng. Bạn có thể cho rằng luôn có một giải pháp cho mê cung.

Ví dụ đầu vào:

3 3 3 3 2 1 S 8 9
3 1 1 3 3 0 6 8 7
1 2 2 4 3 2 5 9 7
1 2 1 5 4 3 4 4 6
1 1 X 6 4 4 5 5 5

Ví dụ đầu ra:

. . . . # # S . #
. # # . . # # . .
. # # # . # # # .
. # # # . # # # .
. . X # . . . . .

3
Bạn có thể di chuyển đến và đi SXtheo bất kỳ hướng nào? Là mê cung luôn luôn có thể giải quyết?
Sở thích của Calvin

Ngoài ra, chúng ta có thể giả sử rằng tất cả các hàng có cùng độ dài không? Và, chỉ cần làm rõ, một "chữ số" có nghĩa là một đơn chữ số thập phân từ 0để 9bao gồm, phải không?
Ilmari Karonen

1
@Calvin Có, bạn có thể di chuyển đến và đi từ S và X theo bất kỳ hướng nào. Mê cung được coi là có thể giải được.
Luke D

1
@IImari Có, tất cả các hàng có cùng độ dài và có, "chữ số" là một chữ số duy nhất từ ​​0 đến 9.
Luke D

Câu trả lời:


3

JavaScript (ES6) 219

Một hàm trả về đúng hay sai. Giải pháp (nếu tìm thấy) là đầu ra trên bàn điều khiển. Nó không cố gắng tìm một giải pháp tối ưu.

f=o=>(r=(m,p,w=0,v=m[p])=>
v>':'
  ?console.log(' '+m.map(v=>v<0?'#':v,m[f]='X').join(' '))
  :v<=w&&[1,-1,y,-y].some(d=>r([...m],d+p,v),m[p]='.')
)(o.match(/[^ ]/g).map((v,p)=>v>'S'?(f=p,0):v>':'?v:v<'0'?(y=y||~p,v):~v,y=0),f)

Ung dung đến chết và giải thích nhiều hơn cần thiết

f=o=>{
  var r = ( // recursive search function
    m, // maze array (copy of)
    p, // current position
    w  // value at previous position
  )=> 
  {
    var v = m[p]; // get value at current position
    if (v == 'S') // if 'S', solution found, output and return true
    {
      m[f] = 'X'; // put again 'X' at finish position
      m = m.map(v => { // scan array to obtain '#'
        if (v < 0) // a numeric value not touched during search
          return '#'
        else  
          return v  
      }).join(' '); // array to string again, with added blanks (maybe too many)
      console.log(' '+m) // to balance ' '
      return true; // return false will continue the search and find all possible solutions
    }
    if (v <= w) // search go on if current value <= previous (if numeric, they both are negative)
    {
      m[p]='.'; // mark current position 
      return [1,-1,y,-y].some(d=>r([...m], d+p, v)) // scan in all directions
    }
    // no more paths, return false and backtrack
    return false
  }

  var f, // finish position (but it is the start of the search)
      y = 0; // offset to next/prev row
  o = o.match(/[^ ]/g) // string to char array, removing ' 's
  .map((v,p) => // array scan to find f and y, and transform numeric chars to numbers 
   {  
     if (v > 'S') // check if 'X'
     {
       f = p;
       return 0; // 'X' position mapped to min value
     }
     if (v > ':') // check if 'S'
       return v; // no change
     if (v < '0') // check if newline
     {
       if (!y) y = ~p; // position of first newline used to find y offset
       return v; // no change
     }
     return ~v; // map numeric v to -v-1 so have range (-1..-10)
   })

  return r(o, f, 0) // start with a fake prev value
}

Kiểm tra trong bảng điều khiển Firefox / FireBug

f('3 3 3 3 2 1 S 8 9\n3 1 1 3 3 0 6 8 7\n1 2 2 4 3 2 5 9 7\n1 2 1 5 4 3 4 4 6\n1 1 X 6 4 4 5 5 5')

Đầu ra

. . . . # # S . #   
. # # . . # # . .   
. # # # . # # # .   
. # # # . # # # .   
. . X # . . . . .  

true  

Chúng tôi dường như chia sẻ một mã không thể tin được lẫn nhau.
seequ

1
@Sieg tại sao, nó không rõ ràng? Tôi sẽ thêm một lời giải thích vào ngày mai
edc65

@Sieg dễ hiểu hơn?
edc65

Thật đáng sợ.
xem

4

C # - 463

Chấp nhận đầu vào thông qua STDIN và sẽ tạo ra một đường dẫn tối ưu, được thử nghiệm cho trường hợp thử nghiệm nhất định, nhưng không thì khác. Giả sử luôn có một giải pháp.

Tôi hơi vội vàng, tôi có thời hạn trong 7 giờ, nhưng điều này có vẻ như quá nhiều niềm vui để bỏ lỡ. Tôi cũng không tập luyện. Nó có thể rất xấu hổ nếu điều này xảy ra, nhưng nó hợp lý chơi golf.

using C=System.Console;class P{static void Main(){var S=C.In.ReadToEnd().Replace("\r","").Replace('X','+');int s=S.IndexOf('S'),e=S.IndexOf('+'),w=S.IndexOf('\n')+1,L=S.Length,i,j=L;var K=new int[L];for(K[s]=s+2;j-->0;)for(i=0;i<L;i+=2){System.Action<int>M=z=>{if((z+=i)>=0&z<L&&S[z]<=S[i]&K[z]<1&K[i]>0&(i%w==z%w|i/w==z/w))K[z]=i+1;};M(2);M(-2);M(w);M(-w);}for(w=e;w!=s+1;w=i){i=K[w]-1;K[w]=-1;}for(;++j<L;)C.Write(j%2<1?K[j]<0?j==s?'S':j==e?'X':'.':'#':S[j]);}}

Mã có ý kiến:

using C=System.Console;

class P
{
    static void Main()
    {
        var S=C.In.ReadToEnd().Replace("\r","").Replace('X','+'); // read in the map, replace X with + because + < 0
        int s=S.IndexOf('S'),e=S.IndexOf('+'),w=S.IndexOf('\n')+1,L=S.Length,i,j=L; // find start, end, width, length

        var K=new int[L]; // this stores how we got to each point as loc+1 (0 means we havn't visited it)

        for(K[s]=s+2; // can't risk this being 0
            j-->0;) // do L passes
            for(i=0;i<L;i+=2) // each pass, look at every location
            {
                // if a whole load of bouds checks, point new location (i+z) at i
                System.Action<int>M=z=>{if((z+=i)>=0&z<L&&S[z]<=S[i]&K[z]<1&K[i]>0&(i%w==z%w|i/w==z/w))K[z]=i+1;};
                // try and move in each direction
                M(2);
                M(-2);
                M(w);
                M(-w);
            }

        for(w=e;w!=s+1;w=i) // find route back
        {
            i=K[w]-1; // previous location
            K[w]=-1; // set this so we know we've visited it
        }

        for(;++j<L;) // print out result
            C.Write(j%2<1?K[j]<0?j==s?'S':j==e?'X':'.':'#':S[j]); // if K < 0, we visit it, otherwise we don't
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.