Bài toán đệ quy trên lưới ô vuông năm 2024
- title Loang trên lưới (BFS/DFS) - Loang trên lưới (BFS/DFS) === - ###### ✍️ Author: 2School Guideline ###### 📋 Content: [TOC] - # Giới thiệu chung Thuật toán loang là một trong những thuật toán được ứng dụng khá nhiều trong công nghệ thông tin nói chung và lập trình thi đấu nói riêng. Nó được áp dụng điển hình vào các trò chơi nổi tiếng như dò mìn, line 98,... . Ngoài được áp dụng trên lưới ra, nó còn được áp dụng trên đồ thị. Thế nhưng trong giới hạn bài viết lần này, bọn mình chỉ giới thiệu cho mọi người về thuật toán loang trên lưới (ma trận). # Thuật toán loang Đúng như tên gọi của nó, thuật toán loang sử dụng nguyên lí vết dầu loang. Từ một vết dầu nhỏ sẽ được loang ra xung quanh. Tương tự như vậy, từ một ô trên ma trận, thuật toán sẽ loang ra xung quanh để giải quyết các bài toán. Như trong trò chơi dò mìn, để giải quyết được trò chơi, bạn phải chọn một điểm ban đầu, và xử lí các thông tin tại đó để dò được các vị trí bãi mìn xung quanh cho tới khi không dò được nữa. ![minesweeper](https://hackmd.io/_uploads/rJG8YXZFa.gif) Hay như khi tìm đường đi trên mê cung, thuật toán sẽ dò tất cả các đường đi xung quanh người chơi để tìm được lối ra cho đến khi không thể dò được nữa. ![87076088-a2c31c00-c1f7-11ea-9a18-e527bd1198cf](https://hackmd.io/_uploads/rJp6dXZKa.gif) Tư tưởng của thuật toán loang chỉ có như vậy, chúng ta sẽ đi đến 2 cách tiếp cận chính của nó. # Tìm kiếm theo chiều sâu (DFS - Depth-first search) ## 1. Bài toán ### 1.1. Đặt vấn đề Ngày xửa ngày xưa, ở một vương quốc nọ, có một nàng công chúa vô cùng xinh đẹp. Tuy nhiên, trong một lần vào rừng dạo chơi, cô đã bị một mụ phù thủy già bắt cóc và nhốt vào một căn phòng kín trong lâu đài rộng lớn của mụ. Triều đình khi hay tin công chúa mất tích đã vô cùng hoảng hốt, nhưng giữa lúc ấy, có một chàng hoàng tử khôi ngô tuấn tú xung phong đi giải cứu công chúa. Nhờ sự giúp đỡ của các vị tiên rừng, vị hoàng tử đã tìm thấy lâu đài hắc ám của mụ phù thủy. Giả sử lâu đài được mô phỏng dưới dạng một ma trận 2 chiều (lưới/bảng) $m * n$, gồm các kí tự: - '**.**' - Phòng trống - '**#**' - Phòng có quái vật - '**A**' - Nơi hoàng tử đang đứng - '**B**' - Nơi công chúa bị giam giữ Đảm bảo chỉ có một ô chứa kí tự '**A**' và một ô chứa kí tự '**B**'. Hãy tìm một đường đi từ vị trí của hoàng tử đến vị trí của công chúa. Biết rằng, từ một ô, ta có thể đi tiếp qua các ô có chung cạnh với nó mà không có quái vật: từ ô có tọa độ $(x, y)$, bạn có thể đi qua các ô $(x + 1, y)$, $(x - 1, y)$, $(x, y + 1)$, $(x, y - 1)$ nếu các ô không được đánh dấu bằng kí tự '**#**'. Nếu không có đường đi, xuất ra "**IMPOSSIBLE**". Nếu tồn tại đường đi: - Xuất ra '**U**' nếu hoàng tử cần đi đến ô $(x - 1, y)$ từ ô $(x, y)$ - Xuất ra '**D**' nếu hoàng tử cần đi đến ô $(x + 1, y)$ từ ô $(x, y)$ - Xuất ra '**L**' nếu hoàng tử cần đi đến ô $(x, y - 1)$ từ ô $(x, y)$ - Xuất ra '**R**' nếu hoàng tử cần đi đến ô $(x, y + 1)$ từ ô $(x, y)$ Bạn chỉ cần xuất một đường đi hợp lệ. (Giới hạn ví dụ: $1 \le n, m \le 1000$) ### 1.2. Ý tưởng giải Ta triển khai ý tưởng giải bài toán: - Sử dụng một mảng đánh dấu, đánh dấu các ô đã đi qua, đảm bảo mỗi ô chỉ được đi qua đúng 1 lần. - Sử dụng một mảng truy vết đường đi: * Từ ô $(x, y)$ đi đến ô $(x - 1, y)$: lưu ký tự '**U**' * Từ ô $(x, y)$ đi đến ô $(x + 1, y)$: lưu ký tự '**D**' * Từ ô $(x, y)$ đi đến ô $(x, y - 1)$: lưu ký tự '**L**' * Từ ô $(x, y)$ đi đến ô $(x, y + 1)$: lưu ký tự '**R**' - Các bước thực hiện: * Từ ô xuất phát, khi tìm thấy một lối đi vào ô khác (ô thuộc phạm vi lâu đài, không có quái vật), nếu ô chưa được đi qua thì đi đến ô đó, đánh dấu ô đã đi qua và lặp lại bước này. * Nếu ô không còn lối đi nào khác (các ô kề không hợp lệ hoặc đã được đi qua hết) thì quay lui về ô trước đó và tìm lối đi khác. * Nếu đi qua ô chứa kí tự '**B**' $\Rightarrow$ tìm thấy công chúa $\Rightarrow$ kết thúc quá trình tìm kiếm và tiến hành xuất đường đi. * Nếu sau khi duyệt qua hết các đường có thể đi mà ô '**B**' chưa được đánh dấu là đã đi qua $\Rightarrow$ không có đường đi từ vị trí của hoàng tử đến chỗ công chúa $\Rightarrow$ xuất ra "**IMPOSSIBLE**" ### 1.3. Cài đặt mẫu ```cpp= include
|