Series: Mô hình hóa các câu đố logic
Phần: 8 / 91. Giới thiệu
Skyscraper là một câu đố logic được mô tả như sau, cho một lưới tượng trưng cho một khu phố nhìn từ trên cao, người chơi cần điền vào mỗi ô chiều cao của một tòa nhà, từ đến , thỏa mãn các điều kiện sau:
- Mỗi hàng và mỗi cột chứa đủ các chiều cao từ đến , mỗi giá trị xuất hiện đúng một lần.
- Các số đặt ở ngoài lưới cho biết số lượng tòa nhà có thể nhìn thấy khi nhìn vào lưới từ phía đó, trong đó một tòa nhà được coi là nhìn thấy nếu nó cao hơn tất cả các tòa nhà khác đứng giữa nó và người quan sát.
Nguồn: Conceptis Puzzles
Để dễ hình dung, hãy nhìn vào ví dụ dưới đây.
Nhìn từ bên trái, tòa nhà cao được nhìn thấy (không có gì đứng trước nó), tòa nhà cao bị che khuất phía sau, tòa nhà cao vượt lên và được nhìn thấy, còn hai tòa còn lại ( và ) đều thấp hơn nên vẫn bị che khuất - vậy có đúng tòa nhà được nhìn thấy.
Dưới đây là ví dụ cho một câu đố Skyscraper cỡ 5×5 và lời giải.
2. Mô hình hóa câu đố
Một số ký hiệu dùng trong bài toán
- là cỡ của lưới
- là tập hợp các cặp biểu diễn tọa độ của các ô đã điền sẵn trên lưới
- là chiều cao được điền trong ô
- là tập hợp các đường ngắm: đọc mỗi hàng theo hai chiều trái-sang-phải và phải-sang-trái, cùng mỗi cột theo hai chiều trên-xuống-dưới và dưới-lên-trên, ta thu được tổng cộng đường ngắm. Với một đường ngắm , () là ô đứng ở vị trí thứ tính từ người quan sát, do đó là ô gần người quan sát nhất
- là số lượng tòa nhà nhìn thấy của đường ngắm
2.1. Biến quyết định
Với mỗi ô trong lưới và một chiều cao , xây dựng biến thỏa mãn
2.2. Các ràng buộc
- Mỗi ô có đúng một chiều cao
- Mỗi hàng chứa đủ các chiều cao từ đến , mỗi giá trị đúng một lần
- Mỗi cột chứa đủ các chiều cao từ đến , mỗi giá trị đúng một lần
- Các ô đã điền sẵn
-
Số lượng tòa nhà nhìn thấy trên mỗi đường ngắm phải đúng bằng yêu cầu.
Nhìn dọc theo một đường ngắm từ phía người quan sát, một tòa nhà được coi là nhìn thấy nếu nó cao hơn mọi tòa nhà đứng giữa nó và người quan sát. Với mỗi đường ngắm , vị trí và chiều cao , ta xây dựng thêm biến trung gian thỏa mãn
Gọi
là số tòa nhà đứng giữa người quan sát và vị trí trên đường ngắm mà cao hơn (tổng này đơn giản bằng khi , vì không có tòa nhà nào đứng trước tòa nhà đầu tiên). Bằng phương pháp hình học ta có thể biểu diễn biến thông qua các biến và bằng các điều kiện sau
Chú ý là ta không cần coi tòa nhà gần nhất hay tòa nhà cao nhất là hai trường hợp đặc biệt. Khi , với mọi , nên các điều kiện trên rút gọn thành : tòa nhà gần nhất luôn được nhìn thấy, bất kể chiều cao của nó là bao nhiêu. Tương tự, khi , với mọi , vì không có tòa nhà nào cao hơn , nên : tòa nhà cao nhất luôn được nhìn thấy, dù nó đứng ở đâu. Cả hai trường hợp biên này tự động đúng theo công thức chung, ta không cần thêm gì cả.
Cuối cùng, yêu cầu về số tòa nhà cần được nhìn thấy của đường ngắm được thỏa mãn bằng điều kiện
2.3. Hàm mục tiêu
Bài toán này không có hàm mục tiêu, bởi vì ta không cần tối thiểu hóa hay tối đa hóa gì cả, việc cần làm chỉ là tìm ra một nghiệm chấp nhận được. Về mặt kỹ thuật, khi lập trình ta có thể để hàm mục tiêu là một hằng số (mình hay chọn số 0).
3. Kết luận
Điểm nhấn của câu đố này nằm ở việc mô hình hóa điều kiện về số tòa nhà nhìn thấy trên 1 đường ngắm. Nhìn qua thì khá đơn giản nhưng lại rất phức tạp khi ta phải tạo thêm cả một hệ biến và điều kiện trung gian để giải quyết.
Tham khảo thêm các câu đố Skyscraper và biến thể tại Krazydad. Code mô hình hóa Skyscraper bằng python có tại Tung-hehe.
Happy modeling!
