Bir fiqurun məhdudlaşdırıcı düzbucaqlısı — koordinat oxlarına paralel olan və verilmiş fiquru tamamilə əhatə edən ən kiçik düzbucaqlıdır.
Sadə şəkildə desək, əgər biz fiquru elə "düzbucağa yerləşdirmək" istəyiriksə ki, onun bütün nöqtələri içəridə olsun, məhdudlaşdırıcı düzbucaq minimal ölçüdə olacaq.
(x_1, y_1) və (x_2, y_2) nöqtələrində sonlanan bir xətti nəzərdən keçirək. Onun məhdudlaşdırıcı düzbucağını tapmaq üçün:
Düzbucağın sol aşağı küncünü təyin edək:
Düzbucağın sağ yuxarı küncünü təyin edək:
Beləliklə, məhdudlaşdırıcı düzbucaq bizim xəttimizə daxil olan (x_1', y_1') və (x_2', y_2') bucaqlara malik olan düzbucaqdır.
Lema. Tutaq ki, düz üzərində iki xətt (x_1, x_2) və (x_3, x_4) verilib, burada x_1 < x_2 və x_3 < x_4. Xəttlər nə zaman və yalnız nə zaman kəsişməzlər ki, ya birinci xətt ikinciyə nisbətən sol tərəfdə yerləşir, ya da ikinci birincinin sol tərəfində yerləşir.
Lema. Tutaq ki, müstəvidə iki düzbucaq verilmişdir (x_1, y_1) - (x_2, y_2) və (x_3, y_3) - (x_4, y_4), burada x_1 < x_2, y_1 < y_2 və x_3 < x_4, y_3 < y_4. Düzbucaqlar nə zaman və yalnız nə zaman kəsişməzlər ki, ya (x_1, x_2) və (x_3, x_4) xəttlərin kəsişməzlər, ya da (y_1, y_2) və (y_3, y_4) xəttlərin kəsişməzlər.
İki xəttin kəsişmə meyarı
İki xətt və nə zaman və yalnız nə zaman kəsişir ki, üç şərt təmin olunur:
1. Məhdudlaşdırıcı düzbucaqlar kəsişir.
2. və nöqtələri düz xəttin əks tərəflərində yerləşir və ya ən azı və ya nöqtəsi xəttində yerləşir. Bu o deməkdir ki,
3. və nöqtələri düz xəttin əks tərəflərində yerləşir və ya ən azı və ya nöqtəsi xəttində yerləşir. Bu o deməkdir ki,
Aşağıda iki xəttin müxtəlif qarşılıqlı yerləşmə halları və onlara uyğun olan vektor çoğrafi vurma qiymətləri verilib.
Növbəti nümunədə hər bir xətt digər xətti olan xətti əhatə edən xətti kəsir. Lakin onların məhdudlaşdırıcı düzbucaqları kəsişmir.
Nümunə
Birinci nümunədə xəttlər kəsişir. İkinci nümunədə isə kəsişmir.
Alqoritmın həyata keçirilməsi
Xəttlərin uclarının koordinatları tam ədədlər olduğuna görə, hesablamalarda yalnız tam ədəd tipi long long istifadə edəcəyik. Gələcəkdə bizə sayının işarəsini müəyyən edən sgn funksiyası lazım olacaq.
int sgn(long long n)
{
return (n > 0) - (n < 0);
}RectanglesIntersects funksiyası və xətti üçün məhdudlaşdırıcı düzbucaqların koordinatlarını arqument olaraq qəbul edir. Əgər (x_1, y_1) - (x_2, y_2) və (x_3, y_3) - (x_4, y_4) düzbucaqları kəsişirsə , əks halda qaytarır.
int RectanglesIntersect(long long x1, long long y1,
long long x2, long long y2,
long long x3, long long y3,
long long x4, long long y4)
{
if (sgn(x3 - x2) * sgn(x4 - x1) > 0) return 0;
if (sgn(y3 - y2) * sgn(y4 - y1) > 0) return 0;
return 1;
}cross funksiyası (A_x, A_y) və (B_x, B_y) iki vektorun vektor fəza vurmasını hesablayır.
long long cross(long long Ax, long long Ay,
long long Bx, long long By)
{
return Ax * By - Ay * Bx;
}intersect funksiyası və xətti arasında kəsişmə olub olmadığını yoxlayır.
int segmentsIntersect(long long x1, long long y1,
long long x2, long long y2,
long long x3, long long y3,
long long x4, long long y4)
{Məhdudlaşdırıcı düzbucaqların kəsişməsini yoxlayırıq. Əgər kəsişmirlərsə, qaytarırıq.
if (!RectanglesIntersect(
min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2),
min(x3, x4), min(y3, y4), max(x3, x4), max(y3, y4))
) return 0;AB, AC, AD vektorlarını qururuq.
long long ABx = x2 - x1, ABy = y2 - y1;
long long ACx = x3 - x1, ACy = y3 - y1;
long long ADx = x4 - x1, ADy = y4 - y1;CD, CA, CB vektorlarını qururuq.
long long CDx = x4 - x3, CDy = y4 - y3;
long long CAx = x1 - x3, CAy = y1 - y3;
long long CBx = x2 - x3, CBy = y2 - y3;Vektor fəza vurmalarını hesablayırıq.
long long ABxAC = cross(ABx, ABy, ACx, ACy); // AB x AC
long long ABxAD = cross(ABx, ABy, ADx, ADy); // AB x AD
long long CDxCA = cross(CDx, CDy, CAx, CAy); // CD x CA
long long CDxCB = cross(CDx, CDy, CBx, CBy); // CD x CBSegmentlərin kəsişmə meyarının və punktlarını yoxlayırıq. Əgər yerinə yetirilməzsə, qaytarırıq. Ehtiyat üçün, artıqzamanları qarşısını almaq üçün, ədədlərin işarələrinin çarpımını nətlə müqayisə etmək lazımdır.
if (sgn(ABxAC) * sgn(ABxAD) > 0) return 0;
if (sgn(CDxCA) * sgn(CDxCB) > 0) return 0;
return 1; // Xəttlər kəsişir
}Programın əsas hissəsi. Giriş məlumatlarını oxuyuruq.
scanf("%lld %lld %lld %lld",&x1,&y1,&x2,&y2);
scanf("%lld %lld %lld %lld",&x3,&y3,&x4,&y4);Xəttlərin kəsişməsini yoxlayırıq.
if (segmentsIntersect(x1, y1, x2, y2, x3, y3, x4, y4))
puts("Yes");
else
puts("No");