Hướng dẫn giải của Bài toán hình chữ nhật 1
Nộp một lời giải chính thức trước khi tự giải là một hành động có thể bị ban.
Lời giải này đang bị ẩn cho đến khi bạn chọn mở ra.
Chúng tôi khuyên bạn nên tự thử giải bài trước. Việc mở lời giải có thể làm lộ mất ý tưởng chính trước khi bạn có cơ hội tự giải.
Bạn phải đăng nhập để mở lời giải này.
Đăng nhậpTác giả: , , ,
Hiểu bài toán
Cho một hình chữ nhật với hai đỉnh đối diện (x1, y1) và (x2, y2) và một điểm (x, y). Kiểm tra xem điểm (x, y) có nằm bên trong hình chữ nhật hay không. Lưu ý: điểm nằm trên cạnh hoặc đỉnh của hình chữ nhật không được coi là nằm trong (nằm trong nghĩa là nằm ở bên trong, không bao gồm biên). Do hai đỉnh đối diện có thể được nhập theo bất kỳ thứ tự nào (ví dụ: đỉnh trên-trái và dưới-phải, hoặc trên-phải và dưới-trái), ta cần chuẩn hóa để tìm ra ranh giới thực tế của hình chữ nhật là các giá trị tọa độ nhỏ nhất và lớn nhất trên từng trục.
Các cách tiếp cận
Cách Kiểm tra trực tiếp theo từng trường hợp
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <limits.h>
int main()
{
int a,b,c,d,e,f;
scanf("%d%d%d%d%d%d",&a,&b,&c,&d,&e,&f);
if((e>a && e<c && f>b && f<d) || (e>a && e<c && f>d && f<d) || (e>c && e<a && f>b && f<d) || (e>c && e<a && f>d && f<b)) printf("YES");
else printf("NO");
}
- Time Complexity: O(1)
- Space Complexity: O(1)
Cách tiếp cận này kiểm tra trực tiếp vị trí của điểm (e, f) so với hai đỉnh (a, b) và (c, d) mà không cần chuẩn hóa tọa độ. Nó sử dụng các điều kiện phức tạp để xử lý tất cả các hướng của hình chữ nhật có thể có:
- (e>a && e<c && f>b && f<d): Trường hợp (a,b) là góc dưới-trái và (c,d) là góc trên-phải.</li>
- (e>a && e<c && f>d && f<d): Trường hợp (a,b) là góc trên-trái và (c,d) là góc dưới-phải.</li>
- (e>c && eb && f<d): Trường hợp (a,b) là góc dưới-phải và (c,d) là góc trên-trái.</li>
- (e>c && ed && f<b): Trường hợp (a,b) là góc trên-phải và (c,d) là góc dưới-trái. Nếu điểm thỏa mãn một trong bốn điều kiện này, nó nằm bên trong hình chữ nhật. Cách này đúng nhưng dễ gây nhầm lẫn và khó đọc.</li>
Cách Chuẩn hóa tọa độ
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int min(int a,int b){
return a<b ?a :b;}
int max(int a,int b){
return a>b ?a :b;}
int main(){
int x1,y1,x2,y2,x3,y3;
scanf("%d%d%d%d%d%d",&x1,&y1,&x2,&y2,&x3,&y3);
if (x3>min(x1,x2) && x3<max(x1,x2) && y3>min(y1,y2) && y3<max(y1,y2)) printf("YES");
else printf("NO");
return 0;
}
- Time Complexity: O(1)
- Space Complexity: O(1)
Đây là cách tiếp cận tối ưu và dễ hiểu nhất. Thay vì xử lý nhiều trường hợp, ta chỉ cần xác định ranh giới thực sự của hình chữ nhật:
- Trục X: Điểm nằm giữa
min(x1, x2)vàmax(x1, x2). - Trục Y: Điểm nằm giữa
min(y1, y2)vàmax(y1, y2). Sử dụng hàmminvàmax(có sẵn hoặc tự định nghĩa), ta kiểm tra xem tọa độ x của điểm có lớn hơn giá trị nhỏ nhất của hai đỉnh và nhỏ hơn giá trị lớn nhất của hai đỉnh hay không (với điều kiện strict inequality>và<để loại trừ biên). Tương tự cho trục Y. Đây là cách viết gọn, ít lỗi và dễ bảo trì.
Cách Sắp xếp lại tọa độ
#include<stdio.h>
int main()
{
int x1, y1, x2, y2, x, y;
scanf ( "%d%d%d%d%d%d", &x1, &y1, &x2, &y2, &x, &y) ;
if(x1 > x2)
{
int temp = x2;
x2 = x1;
x1 = temp;
}
if(y1 > y2)
{
int temp = y2;
y2 = y1;
y1 = temp;
}
if(x > x1 && x < x2 && y > y1 && y < y2)
{
printf("YES");
}
else
{
printf("NO");
}
}
- Time Complexity: O(1)
- Space Complexity: O(1)
Phương pháp này cũng dựa trên việc chuẩn hóa tọa độ nhưng thực hiện bằng cách hoán đổi giá trị trực tiếp. Nếu x1 > x2, ta hoán đổi chúng để đảm bảo x1 là tọa độ nhỏ hơn và x2 là tọa độ lớn hơn. Tương tự với y1 và y2. Sau khi sắp xếp lại, hình chữ nhật sẽ có góc dưới-trái là (x1, y1) và góc trên-phải là (x2, y2). Lúc này, việc kiểm tra điểm (x, y) nằm trong hình chữ nhật chỉ cần kiểm tra điều kiện x1 < x < x2 và y1 < y y < y2. Cách này cũng hiệu quả và dễ hiểu, nhưng đòi hỏi phải sửa đổi giá trị biến đầu vào.
Phân tích độ phức tạp
| Cách tiếp cận | Time | Space | Tên |
|---|---|---|---|
| 1 | O(1) | O(1) | Kiểm tra trực tiếp theo từng trường hợp |
| 2 | O(1) | O(1) | Chuẩn hóa tọa độ |
| 3 | O(1) | O(1) | Sắp xếp lại tọa độ |
Bài học kinh nghiệm
- Vấn đề chính là xử lý việc hai đỉnh đối diện có thể được nhập theo bất kỳ thứ tự nào (ví dụ: góc trên-trái và dưới-phải, hoặc dưới-phải và trên-trái).
- Cách tiếp cận tốt nhất là chuẩn hóa tọa độ để xác định ranh giới thực tế (min, max) của hình chữ nhật trên mỗi trục tọa độ.
- Điều kiện kiểm tra 'nằm trong' (strictly inside) yêu cầu sử dụng toán tử so sánh nghiêm ngặt (
>và<) thay vì (>=và<=).
Lỗi thường gặp
- Quên kiểm tra các trường hợp khác nhau của hai đỉnh (ví dụ: chỉ kiểm tra khi đỉnh đầu là góc dưới-trái).
- Sử dụng sai toán tử so sánh (dùng
>=hoặc<=thay vì>và<)导致 điểm nằm trên biên bị tính là 'nằm trong'. - Lỗi logic khi kiểm tra các trường hợp tọa độ âm hoặc dương.
Bình luận