Статья Автор: Лебедев Дмитрий Алексеевич

КЕГЭ-6 Просто Треугольник (Черепашка)

Предположим, что есть задание типа 42611:

Черепахе был дан для исполнения следующий алгоритм:
Повтори 10 [Налево 60 Вперёд 300 Налево 60]
(
В начальный момент Черепаха находится в начале координат, её голова направлена вдоль положительного направления оси ординат, хвост опущен.)
Определите, сколько точек с целочисленными координатами будут находиться внутри области, ограниченной линией, заданной данным алгоритмом. Точки на линии следует учитывать

Условие "несколько необычное", но в сборниках от ФИПИ похожее встречается.
Из условия следует, что
  • решать методом "подсчета точек" явно не стоит
  • рисовать сетку тоже смысла не имеет, но нарисуем оси
  • нарисуем чертеж и подумаем

Нарисуем задание на бумаге в клеточку и получим примерно следующее
 

 

Идея решения будет состоять в том, что треугольник есть "пересечение" двух углов (любых), а четырехугольник есть пересечение двух противоположных углов.
Значит, если научимся определять принадлежность точки углу, то сможем решить задание
Сначала (также, как и для прямоугольников) напишем простой код с выводом координат точек A, B, C
 

 

Скопируем значения A,B,C. Нужны вещественные значения (точности должно хватить) 

A = (0.00, 0.00)
B = (-259.81, 150.00)
C = (-259.81, -150.00)
Задача упрощается тем, что есть сторона BC параллельная оси координат. Это позволяет получить простое решение (для подсчета внутренних точек)
одним из следующих соображений:

Точка P с координатами (x,y) лежит внутри \(\triangle ABC\) тогда и только тогда, когда \(0<\angle CBP<60^o\ и\ 0<\angle PCB<60^o \)
Проверить это можно несколькими способами, например:
1. через тангенсы, поскольку \(\tan(\angle CBP ) = \frac{x-B_x}{B_y - y}\), \(\tan(\angle PCB ) = \frac{x-C_x}{y - C_y}\)
2. через косинусы, которые можно найти через скалярные произведения
3. используя полярные координаты (вернее фазу), вычисление которых производить не надо, а просто "получить их автоматически"

Отметим, что 

первый способ "легко работает" только при наличие стороны параллельной осям координат
второй способ требует аккуратности
третий способ использует библиотеки
существует четвертый способ, использующий "косое" и "скалярное" произведение векторов
(его разберем для многоугольников, где остальное будет работать "плохо" )

Для понимания, реализуем все три способа. Начнем с тангенсов


​​​

 

Теперь через скалярное произведение определяем косинус угла \(\cos(\overline a,\overline b) =\frac{\overline a\cdot \overline b}{|\overline a|\cdot|\overline b|}\)
Таким образом \(\cos\angle CBP = \frac{(C_x-B_x)(x-B_x) + (C_y-B_y)(y-B_v)}{|BC|\cdot|PB|}\), а \(\cos\angle PCB = \frac{(B_x-C_x)(x-C_x) + (B_y-C_y)(y-C_y)}{|CB|\cdot|PC|}\)
Для данной задачи можно упростить формулы, но напишем решение в общем виде
Проверка того, что угол меньше 60 градусов преобретает вид - косинус меньше 0,5

 

Оба метода дают одинаковые ответы, но требуют правильной настройки параметров циклов.
Лучше настраивать от и до так, чтобы вершины не входили в перебор.
Теперь попробуем способ, использующий записть точек как комплексных чисел и библиотеку cmath
Пару координат можно определить как complex(x,y) - на компьютере это будет комплексный формат.
Используя библиотеку cmath с помощью метода polar() для "комплесной точки" можно получить полярные координата в формате (r,u), где r - расстояние до начала координат, а u - фаза (полярный угол)
(Аналогичное можно получить и с помощью методов библиотеки math, но использование cmath интереснее)

 

Какой метод избрать? Каждый "выбирает для себя", но хочется предложить "метод комплексных чисел", так как:
  • простота действай
  • не  надо отдельно проверять точки на сторонах
  • не надо подбирать параметры цикла
  • не зависит от вида треугольника
  • может быть усовершенствован до "метод уравнений прямых" (будет далее)
Опасности - выбираемые углы должны быть "одинаково ориентированы", Если не учитывать расстояние до вершины, то можно пропустить "целочисленную" вершину
Поясним на примере: Возьмем и поменяем в решении точки A и В местами и уберем умножение на .uPB[0] (это расстояние до вершины)

 

Получили другой результат, причем результат зависит от интервалов просмотра x, y
Дело в том, что теперь угла не сонаправлены и угол CBA больше развернутого и надо чтобы rb имело положительное значение.
Это понимание будет нужно при "решении четырехугольников".
Если это поправить, то снова  будет правильный ответ.
Надежнее считать только внутренние точки и добавлять точки на сторонах (это несложно сделать)

ЗЫ. Если изменение/увеличение интервалов просмотра для x,y влияет на ответ, то есть ошибка в ориентации углов.
 
Печать