Занятие № 5
Задачи на плоскости.
Пример 1
Даны 3 точки A, B и C. Определить, лежат ли они на одной прямой.
Все точки задаются своими координатами – парами целых чисел.
Решение
Нужно выяснить, параллельны ли векторы AB и AC. Мы можем вычислить координаты этих векторов – это просто разности координат точек. Для того чтобы векторы с координатами (x1, y1) и (x2, y2) были параллельны, нужно, чтобы существовало такое число a, что x2 = a * x1 и y2 = a * y1. Поэтому первая идея состоит в том, чтобы проверить равенство x2 / x1 = y2 / y1. Однако так поступать нельзя, так как x1 или y1 могут оказаться равными 0. Вместо этого мы проверяем равенство x1 * y2 = x2 * y1.
Приведем пример функции на Pascal'е для решения этой задачи, введя, для удобства записи, тип point.
type
point = record
x, y: integer;
end;
function isLine (A, B, C: point) : boolean;
begin
isLine := ((B.x - A.x) * (C.y - A.y) - C.x - A.x) * (B.y - A.y) = 0);
end;
Пример 2
Даны 3 точки A, B и C, не лежащие на одной прямой. Определить, является обход `A->B->C` обходом по часовой стрелке или против часовой стрелки.
Решение
function isClockWise (A, B, C: point): boolean;
begin
isClockWise := ((B.x - A.x) * (C.y - A.y) - (C.x - A.x) * (B.y - A.y) < 0);
end;
Пример 3
a)Даны 4 точки A, B, C и D. Определить, пересекаются ли отрезки AC и BD.
b)Даны 4 точки A, B, C и D. Определить, является ли четырехугольник ABCD выпуклым.
Замечание: если 3 или все 4 вершины оказываются на одной прямой, то четырехугольник считается выпуклым.
Решение
Отрезки AC и BD пересекаются тогда и только тогда, когда четырехугольник ABCD выпуклый, так что это одна и та же задача. Это верно, по крайней мере, если не обращать внимания на особые случаи, то есть на ситуации, когда точки лежат на одной прямой. Такие случаи можно разобрать отдельно.
Для того, чтобы четырехугольник ABCD был выпуклым, необходимо и достаточно, чтобы все 4 обхода
`A->B->C,\ B->C->D,\ C->D->A,\ D->A->B` были бы обходами в одну сторону: либо по часовой стрелке, либо против.
Приведем пример функции, где мы используем знакомый уже тип point и функцию из предыдущего задания.
function isConvex4(A, B, C, D: point): boolean;
begin
if (isClockWise(A, B, C)) then
isConvex4 := isClockWise(B, C, D) and
isClockWise(C, D, A) and
isClockWise(D, A, B)
else
isConvex4 := (not isClockWise(B, C, D)) and
(not isClockWise(C, D, A)) and
(not isClockWise(D, A, B));
end;
Эта функция работает в не особых случаях. Программа, которая удовлетворяет требованию задания может, например, проверять сначала, не лежат ли какие-то 3 точки на одной прямой, вызывая 4 раза функцию isLine.
#include <stdio.h>
#include "math.h"
void N(double &a, double &b)
{
double c;
if(a<b){
c=a;
a=b;
b=c;
}
}
int main(){
double P[3], gl, o;
scanf("%lf%lf%lf", &P[0],&P[1],&P[2]);
N(P[0],P[1]);
N(P[0],P[2]);
N(P[1],P[2]);
gl=acos((P[1]*P[1]+P[0]*P[0]-P[2]*P[2])/2/P[1]/P[0]);
if(gl>asin(1.0)/2)o=P[0]*P[0]/4;
else{ if(cos(gl)*P[0]<=P[1])
o=sin(gl)*P[0]*cos(gl)*P[0]/2;
else o=tan(gl)*P[1]*P[1]/2;
}
printf("%0.6f", o);
}
Системы счисления
{$R-}
var
i, j, alen, blen: longint;
a, b: array[1..30000] of byte;
procedure readnum;
var
c: char;
hi, lo, buf: longint;
begin
hi := 0;
while not eoln do
begin
read(c);
inc(hi);
case c of
'0'..'9': a[hi] := ord(c) - ord('0');
'A'..'Z': a[hi] := ord(c) - ord('A') + 10;
end;
end;
alen := hi;
lo := 1;
while lo < hi do
begin
buf := a[hi];
a[hi] := a[lo];
a[lo] := buf;
inc(lo); dec(hi);
end;
end;
function ZeroA: boolean;
var
index: longint;
begin
ZeroA := false;
for index := 1 to alen do
if a[index] <> 0 then
exit;
ZeroA := true;
end;
function reminder: longint;
var
rem, index: longint;
begin
rem := 0;
for index := alen downto 1 do
begin
rem := rem * i + a[index];
a[index] := rem div j;
rem := rem mod j;
end;
reminder := rem;
end;
procedure printB;
var
index, i: longint;
c: char;
begin
for index := 30000 downto 1 do
if b[index] <> 0 then
break;
for i := index downto 1 do
begin
case b[i] of
0..9: c := chr(b[i] + ord('0'));
10..35: c := chr(b[i] - 10 + ord('A'));
end;
write(c);
end;
end;
begin
assign(input, 'input.txt'); reset(input);
assign(output, 'output.txt'); rewrite(output);
readln(i, j);
readnum;
blen := 0;
repeat
inc(blen);
b[blen] := reminder;
until ZeroA;
printB;
end.