Вход


Главная страница >> Учебный процесс >> Задачник >> Олимпиадные задачи (с решениями) >> Геометрия >> Номер 18

[Назад]    [Содержание ]    [Вперед]

  


Номер 18


  Условие: Номер 18


Задача 18. На двумерной плоскости задано N точек с координатами (X1,Y1), (X2,Y2), ..., (Xn,Yn). Написать программу, которая из этих точек выделяет вершины квадрата, содержащего максимальное число заданных точек. ПРИМЕЧАНИЕ: предполагается, что точки, расположенные на сторонах квадрата, принадлежат ему.

  Решение задачи: Номер 18


Решение задачи 18. Это переборная задача. Обратите внимание, что стороны квадрата могут и не быть параллельны осям координат! Каждую из N точек мы последовательно рассматриваем в качестве верхнего левого угла квадрата, каждую из оставшихся N-1 - как нижнюю правую вершины и смотрим, есть ли для них в этом множестве из N точек точки, соответствующие верхнему правому и нижнему левому углу. Если да, то подсчитываем, сколько точек лежат в данном квадрате. Пусть координата левого верхнего угла (x1,y1), нижнего правого (x2,y2), тогда координата пересечения диагоналей четырехугольника ((x1+x2)/2,(y1+y2)/2); координата верхнего правого угла ((x1+x2)/2+[y1-(y1+y2)/2],(y1+y2)/2+[x1-(x1+x2)/2])= =((x1+x2+y1-y2)/2, (x1-x2+y1+y2)/2), нижнего левого - ((x1+x2-y1+y2)/2,(-x1+x2+y1+y2)/2) (Постройте чертеж и проверьте !). Для (x1,y2) и (x2,y2) должны выполняться следующие неравенства: x1<=x2, y1>=y2 (иначе это будут уже не левый верхний и правый нижний углы квадрата). Проверка принадлежности точки фигуре - см. задачу 8. Программа: {В исходном множестве поочередно перебираются все пары точек.} {Предполагая, что отрезок, соединяющий эти точки, является ребром} {квадрата строим квадрат и смотрим, все ли его вершины имеются в} {исходном множестве. Если все, то определяем, сколько точек из} {исходного множества лежит внутри этого квадрата. Если это число} {превосходит старый рекорд то запоминаем найденный квадрат.} { } {$A-,B-,D-,E+,F-,I+,L-,N-,O-,R-,S-,V-} {$M 65520,0,655360} uses crt; const maxn = 100;{ Максимальное число точек } type xy = record x,y : real end; { Тип для записи координат точек } var m : array[1..maxn] of xy; { Координаты точек множества } i,j,g,k,n,p : word; { вспомогательные переменные } num : word; { для записи числа точек в текущем квадрате } rec : word; { для записи числа точек в лучшем квадрате } a1,b1,c1 : real; { вспомогательные переменные } r,c : array[1..5] of xy;{ для записи вершин квадратов } f1,f2 : boolean; o : array[1..4] of shortint; Function sign(a : real) : shortint;{ Функция signum } begin if a<0 then sign:=-1 else if a>0 then sign:=1 else sign:=0 end; { нахождение коэффициентов прямой, проходящей через точки x1,y1 и x2,y2 } procedure getabc(x1,y1,x2,y2:real; var a,b,c:real); begin a:=y2-y1; b:=x1-x2; c:=-(a*x1+b*y1) end; begin write('Введите число точек...'); readln(n); for i:=1 to n do begin write('Введите координаты ',i,'-ой точки...');readln(m[i].x,m[i].y); end; rec:=0;{ Обнуление рекорда } for i:=1 to n do { Перебор всех квадратов, для которых отрезок m[i]-m[j] } for j:=1 to n do { является ребром } if i<>j then begin c[1]:=m[i]; c[2]:=m[j]; { Определение вершин квадрата } c[3].x:=c[2].x+(c[1].y-c[2].y); c[3].y:=c[2].y+(c[2].x-c[1].x); c[4].x:=c[1].x+(c[1].y-c[2].y); c[4].y:=c[1].y+(c[2].x-c[1].x); c[5]:=c[1]; num:=0; { Проверка на наличие всех вершин квадрата в исходном множестве точек } f1:=false; f2:=false; for g:=1 to n do if (m[g].x=c[3].x) and (m[g].y=c[3].y) then f1:=true; for g:=1 to n do if (m[g].x=c[4].x) and (m[g].y=c[4].y) then f2:=true; if (c[1].x=c[2].x) and (c[1].y=c[2].y) then f1:=false; if f1 and f2 then {Если все вершины квадрата есть в исходном множестве} for k:=1 to n do { то определяем число точек в квадрате} begin for g:=1 to 4 do begin getabc(c[g].x,c[g].y,c[g+1].x,c[g+1].y,a1,b1,c1); o[g]:=sign(a1*m[k].x+b1*m[k].y+c1); end; if ((o[1]=o[2]) and (o[2]=o[3]) and (o[3]=o[4])) or ((o[1]=o[2]) and (o[2]=o[3]) and (o[4]=0)) or ((o[1]=o[2]) and (o[2]=o[4]) and (o[3]=0)) or ((o[1]=o[3]) and (o[3]=o[4]) and (o[2]=0)) or ((o[2]=o[3]) and (o[3]=o[4]) and (o[1]=0)) or ((m[k].x=c[1].x) and (m[k].y=c[1].y)) or ((m[k].x=c[2].x) and (m[k].y=c[2].y)) or ((m[k].x=c[3].x) and (m[k].y=c[3].y)) or ((m[k].x=c[4].x) and (m[k].y=c[4].y)) then inc(num); end; if rec<num then begin r:=c; rec:=num end; end; if rec=0 then { Не найдено ни одного квадрата } begin writeln('Не найдено ни одного квадрата.'); halt end; { Вывод результатов } write('Лучший квадрат : '); for i:=1 to 3 do write('(',r[i].x:2:2,',',r[i].y:2:2,')-'); writeln('(',r[4].x:2:2,',', r[4].y:2:2,').'); writeln('В нем находится ',rec,' точек.'); end.

Назад



[Назад]    [Содержание ]    [Вперед]

  


  
За содержание страницы отвечает Гончарова М.Н.
©
Кафедра СПиКБ, 2002-2017