Круг и множество точек
Задача:
На плоскости заданы множество точек М и круг. Выбрать из М две различные точки так, чтобы наименьшим образом различались количества точек в круге, лежащие по разные стороны от прямой, проходящей через эти точки.
Описание:
Решение задачи можно разбить на несколько пунктов:
1) выборка двух точек из n без повторений реализована циклами
for i:= 1 to n-1 do
for j:= i+1 to n do begin
...
end;
2) внутри этого цикла производится перебор всех точек, и выясняется лежит ли проверяемая точка внутри круга (условие (x-rx)2+(y-ry)2 > r2 означает, что расстояние от точки до центра круга меньше его радиуса).
Если точка внутри круга подставляем её координаты( x и y ) в уравнение прямой
где x1,y1,x2,y2 - координаты первой и второй выбранных выше точек соответственно.
Подставляем x и y:
если , то точка находиться выше прямой
если , то ниже прямой.
Может оказаться так, что точки имеют одинаковую координату по x, поэтому в уравнении получиться деление на ноль. Поэтому перед подстановкой в неравенство(уравнение прямой), сравним абсциссы точек, и если они равны, все точки будут лежать либо справа либо слева от прямой. Чтобы выяснить, где лежит каждая проверяемая точка будем сравнивать первую координату точки с первой координатой любой из двух выбранных точек(в нашем примере сравнивается с координатой первой точки).
3) После каждого сравнения увеличиваем счётчики high - для подсчёта точек выше прямой или справа и счётчик low - для подсчёта точек ниже прямой и ,соответственно, слева от неё.
Каждый раз найдя решение лучше предыдущего сохраняем его в переменных res, t1, t2.
Код:
|
|
program Krug;
const
n = 5; {число точек}
var
i,j,t,r,rx,ry,high,low,res: integer; {i,j,t - счётчики}
M: array[1..n,1..2] of integer;
t1,t2: integer; {в них запишем номера двух точек, - решение задачи}
Begin
rx:= 0; {x-координата центра круга}
ry:= 0; {y-координата центра круга}
r:= 8; {радиус круга}
Randomize; {координаты точек задаём пройзвольно}
for i:= 1 to n do begin
M[i,1]:= Random(21)-10; {из диапазона [-10,10]}
M[i,2]:= Random(21)-10;
end;
for i:= 1 to n do begin {вывод координат точек на экран}
Write(M[i,1]:3,' ',M[i,2]:3);
Writeln;
end;
res:= n+1; {инициализация просто большим числом}
for i:= 1 to n do
if sqr(M[i,1]-rx)+sqr(M[i,2]-ry) > sqr(r) then inc(j); {в j считаем точки вне круга}
if j = n then begin
Writeln('Все точки вне круга!');
Readln;
Exit;
end;
for i:= 1 to n-1 do {выборка двух точек из n без повторений}
for j:= i+1 to n do begin {-//-}
high:= 0; {начальные условия: high - для подсчёта точек выше прямой или справа, если}
low:= 0; {прямая параллельна Oy; low - для подсчёта точек ниже и ,соответственно, слева}
for t:= 1 to n do begin {перебираем все точки}
if sqr(M[t,1]-rx)+sqr(M[t,2]-ry) < sqr(r) then {которые внутри круга}
begin
if (M[i,1]=M[j,1]) and (M[t,1] > M[i,1]) then inc(high); {прямая||Oy, точки справа}
if (M[i,1]=M[j,1]) and (M[t,1] < M[i,1]) then inc(low); {прямая||Oy, точки слева}
if (M[i,1] <> M[j,1]) then begin {прямая не||Oy, подставляем координаты в уравнение прямой}
if M[t,2] > ((M[i,2]-M[j,2])/(M[i,1]-M[j,1]))*(M[t,1]-M[i,1])+M[i,2] then inc(high);
if M[t,2] < ((M[i,2]-M[j,2])/(M[i,1]-M[j,1]))*(M[t,1]-M[i,1])+M[i,2] then inc(low);
end;
end;
end;
if res > abs(high - low) then begin {вычисляем разницу high - low по модулю}
res:= abs(high - low); {если меньше результата, полученного ранее}
t1:= i; {эти две точки будут новым решением}
t2:= j;
end;
end;
Writeln;
Writeln(res); {вывод разницы в количестве точек по разные стороны от прямой}
Writeln(M[t1,1]:3,' ',M[t1,2]:3); {и самих точек на экран}
Writeln(M[t2,1]:3,' ',M[t2,2]:3);
Readln;
End.
|
|