Dưới đây là một cách tiếp cận hoàn toàn khác nhau:
Bạn giữ aa ma trận 2d kích thước [Chiều dài, 2] Chiều dài được kích thước của bản đồ của bạn (tôi giả sử chiều rộng đối xứng/chiều cao, nhưng nếu không chỉ chọn một trục). Tôi sẽ gọi cột thứ nhất (Chiều dài) (bạn có thể xoay toàn bộ thuật toán 90 độ và gọi hàng này). Mỗi cột chứa 2 giá trị - Vị trí nhỏ nhất & Vị trí tối đa của phạm vi hợp lệ trong cột.
Bạn điền vào ma trận này với các thuật toán sau đây:
Bắt đầu với dấu chấm cột, tìm & cửa hàng min & tối đa vị trí của dãy liền kề trên & dưới dấu chấm. Nếu chấm là tại x, y:
int colMin, colMax;
for(colMin = y; colMin > 0;) {
if(Matrix[x, colMin - 1].IsValid)
colMin--;
else break;
}
for(colMax = y; colMax < maxHeight;) {
if(Matrix[x, colMax + 1].IsValid)
colMax++;
else break;
}
MinMaxValid[x, 0] = colMin;
MinMaxValid[x, 1] = colMax;
Bạn tiến hành theo cả hai hướng một cách độc lập với các thuật toán sau đây:
int minCol = 0, maxCol = maxWidth; // These hold the min/max range of valid columns
for(int col = x - 1; col >= 0; col--) {
for(colMin = y; colMin > MinMaxValid[col + 1, 0];) { // Cell is only valid if it overlaps to the next range
if(Matrix[col, colMin - 1].IsValid)
colMin--;
else break;
}
for(colMax = y; colMax < MinMaxValid[col + 1, 1];) { // Cell is only valid if it overlaps to the next range
if(Matrix[col, colMax + 1].IsValid)
colMax++;
else break;
}
if((colMax - colMin) >= (x - col)) { // if the found range is smaller than the distance for x, it can't be a part of the square
MinMaxValid[col, 0] = colMin;
MinMaxValid[col, 1] = colMax;
}
else {
minCol = col + 1;
break; // We're done on this side
}
}
for(int col = x + 1; col < maxWidth; col++) {
for(colMin = y; colMin > MinMaxValid[col - 1, 0];) { // Cell is only valid if it overlaps to the previous range
if(Matrix[col, colMin - 1].IsValid)
colMin--;
else break;
}
for(colMax = y; colMax < MinMaxValid[col - 1, 1];) { // Cell is only valid if it overlaps to the previous range
if(Matrix[col, colMax + 1].IsValid)
colMax++;
else break;
}
if((colMax - colMin) >= (col - x)) { // if the found range is smaller than the distance for x, it can't be a part of the square
MinMaxValid[col, 0] = colMin;
MinMaxValid[col, 1] = colMax;
}
else {
maxCol = col - 1;
break; // We're done on this side
}
}
Bây giờ bạn đã MinMaxValid bạn điền. Phần tiếp theo là chạy qua các hàng và tìm ra vuông lớn nhất:
int maxSquareSize = 0, maxSquareCol = minCol;
for(int col = minCol; (MinMaxValid[col, 1] - MinMaxValid[col, 0]) >= (maxCol - col); col++) {
for(int squareSize = MinMaxValid[col, 1] - MinMaxValid[col, 0] + 1; squareSize > maxSquareSize; squareSize--) {
if((Min(MinMaxValid[col, 1], MinMaxValid[col + squareSize - 1, 1]) - Max(MinMaxValid[col, 0], MinMaxValid[col + squareSize - 1, 0])) >= (squareSize) {
maxSquareSize = squareSize;
maxSquareCol = col;
break;
}
}
}
Phần cuối cùng làm việc như thế này:
Bất kỳ cột có thể tham gia vào một hình vuông chỉ lớn như đó là chiều cao. Để làm như vậy, liên kết của phạm vi cột hiện tại và phạm vi tại col + squareSize - 1
phải có kích thước tối thiểu là square.
Bây giờ đến phần tốt nhất! Bất cứ khi nào cảnh thay đổi (Hình vuông trở nên không hợp lệ, dấu chấm di chuyển, v.v.) bạn chỉ có thể làm mất hiệu lực một phạm vi nhất định của ma trận MinMaxValid và đánh giá lại khi cần thiết. Tôi không bao gồm logic này vì câu trả lời này đủ dài, nhưng đó là phần dễ dàng (Về cơ bản, bạn giảm phạm vi cột để phù hợp với kịch bản mới và quét lại cả hai hướng).
Tôi phải nói rằng tôi chưa thử cái này, nhưng ngay cả khi nó không hoạt động (Và hãy cho tôi biết để tôi có thể xóa bình luận này :-), nó phải gần với một giải pháp hợp lệ.
Có nhiều thứ khác nhau có thể được thực hiện, nhưng tùy thuộc vào kích thước tối đa của lưới của bạn, có thể hầu hết các tối ưu hóa sẽ không hiệu quả do chi phí khởi tạo lớn. Có kích thước tối đa được xác định trước không? – Amit
@Làm tốt, lưới có thể là hàng trăm đơn vị theo chiều ngang và theo chiều dọc, nhưng tôi đã nhận thấy rằng có thể hình vuông lớn nhất hiếm khi lớn hơn 10 và không bao giờ lớn hơn 20. Tôi muốn nói kích thước phổ biến nhất ' m nhận được (đối với hình vuông tối đa có thể) thường là 3-6. – RocketNuts
@Amit kể từ khi bạn đề cập đến 'khởi tạo', tôi đã thêm một nhận xét về bản đồ là hơi năng động. Tôi thực sự nghĩ đến việc tính toán trước tất cả các loại thông tin hộp giới hạn, nhưng điều đó không thực sự hoạt động ở đây vì bản đồ không cố định. – RocketNuts