Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/21: Рейтинг темы: голосов - 21, средняя оценка - 4.86
 Аватар для Ternsip
670 / 198 / 29
Регистрация: 10.05.2012
Сообщений: 595

Пересечение двух окружностей

11.05.2013, 22:57. Показов 4184. Ответов 10

Студворк — интернет-сервис помощи студентам
Есть такая задачка.

Вам даны две окружности в плоскости. Найдите все их различные точки пересечения.

В силу большой требуемой точности рекомендуется использовать более чем 8-байтные вещественнозначные типы при вычислениях. Вот тут сразу вопрос, это какие типы ? double 8 байтный, больше не знаю. Пишу на MVSC++ 2012

Входные данные
В первой строке M (1 <= M <= 10000) -- количество тестов. Следующие 2M строк описывают сами окружности. Каждая окружность описывается 3 числами: координатами центра и радиусом.
Все числа в файле целые, известно, что все координаты от -1000 до +1000, и радиус больше нуля и не превосходит 1000.

Выходные данные
Для каждого теста выведите сообщение:
There are no points!!! -- если нет точек пересечения;
There are only i of them.... -- если есть только i точек пересечения. Выведите в след. i строках сами точки, сортируя их по x в первую очередь и по y во вторую. Выводите их с 12 знаками после запятой.
I can't count them - too many points -- если их бесконечное число.
Разделяйте выводы для разных тестов пустой строкой.

Пример

Ввод
1
0 0 2
4 0 2
Вывод
There are only 1 of them....
2.00000000000000 0.00000000000000

Решал так :
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <set>
#include <vector>
#include <limits>
#include <stdio.h>
#include <string>
#include <queue>
#include <time.h>
 
using namespace std;
 
double eps = 1e-18;
 
bool comp(long double a, long double b){
    return (abs(a-b) < eps);
} 
 
void circle_line(long double a, long double b, long double c, long double r, long double x1, long double y1){
    long double x0 = -a*c/(a*a+b*b);
    long double y0 = -b*c/(a*a+b*b);
    if (c*c > r*r*(a*a+b*b)+eps){
        printf("There are no points!!!\n");
    }else if (comp(c*c, r*r*(a*a+b*b))) {
        printf("There are only 1 of them....\n");
        printf("%.14lf %.14lf\n", x0 + x1, y0 + y1);
    } else {
        printf("There are only 2 of them....\n");
        long double d = r*r - c*c/(a*a+b*b);
        long double mult = sqrt (d / (a*a+b*b));
        long double ax = x0 + b * mult;
        long double bx = x0 - b * mult;
        long double ay = y0 - a * mult;
        long double by = y0 + a * mult;
        if (ax > bx || (ax == bx && ay > by)) {
            swap(ax, bx);
            swap(ay, by);
        }
        printf("%.14lf %.14lf\n%.14lf %.14lf\n", ax + x1, ay + y1, bx + x1, by + y1);
    }
}
 
void circle_circle (long double x1, long double y1, long double r1, long double x2, long double y2, long double r2){
    if (comp(x1, x2) && comp(y1, y2)) {
        if (!comp(r1, r2)){
            printf("There are no points!!!\n");
        } else {
            printf("I can't count them - too many points :(\n");
        }
        return;
    }
    x2 -= x1;
    y2 -= y1;
    circle_line(- 2.0 * x2, - 2.0 * y2, x2*x2 + y2*y2 + r1*r1 - r2*r2, r1, x1, y1);
}
 
int main() {
    freopen("input.txt", "rt", stdin);
    freopen("output.txt", "wt", stdout);
    int t;
    cin >> t;
    while (t > 0) {
        long double x1, y1, r1, x2, y2, r2;
        scanf("%lf%lf%lf%lf%lf%lf", &x1, &y1, &r1, &x2, &y2, &r2);
        circle_circle(x1, y1, r1, x2, y2, r2);
        printf("\n");
        t--;
    }
    return 0;
}
(Доступ к контестору только из Саратова http://acm.sgu.ru/univer/)

Добавлено через 39 секунд
В чём ошибка ?

Добавлено через 50 секунд
http://e-maxx.ru/algo/circles_intersection можно руководствоваться

Добавлено через 3 минуты
статус :
Test.1: OK with Time 0 ms
Test.2: OK with Time 0 ms
Test.3: OK with Time 0 ms
Test.4: OK with Time 15 ms
Test.5: OK with Time 0 ms
Test.6: WA with Time 31 ms
Test.7: WA with Time 31 ms
Test.8: OK with Time 62 ms
Test.9: OK with Time 31 ms
Test.10: OK with Time 62 ms
Test.11: OK with Time 62 ms
Test.12: OK with Time 62 ms
Test.13: WA with Time 62 ms
Test.14: WA with Time 46 ms
Test.15: WA with Time 78 ms
Test.16: WA with Time 0 ms
Test.17: OK with Time 15 ms
Test.18: WA with Time 15 ms
Test.19: OK with Time 15 ms

Добавлено через 5 минут
Мне кажется потеря точности

Добавлено через 47 минут
upup

Добавлено через 4 часа 16 минут
upb

Добавлено через 2 часа 28 минут
апп
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
11.05.2013, 22:57
Ответы с готовыми решениями:

Пересечение двух окружностей
На плоскости даны две окружности. Требуется проверить, пересекаются ли они. Входные данные Входной файл INPUT.TXT состоит из двух...

Задача на пересечение двух окружностей
Всем привет! Прошу вашей помощи в решении задачи так как я уже дней пять над ней мучаюсь и все не выходит. Даны две окружности в...

Пересечение двух прямых и проверка на пересечение
Доброго времени суток слизал функцию проверки отсюда:/segments_intersection_checking на всякий случай у меня она выглядит так: int...

10
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
11.05.2013, 23:04
...

Добавлено через 1 минуту
Цитата Сообщение от Ternsip Посмотреть сообщение
Вот тут сразу вопрос, это какие типы ? double 8 байтный, больше не знаю. Пишу на MVSC++ 2012
Ты же используешь long double !?
0
 Аватар для Ternsip
670 / 198 / 29
Регистрация: 10.05.2012
Сообщений: 595
11.05.2013, 23:54  [ТС]
lazybiz, а он в MVSC++ 2012 ничем не отличается от double
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
12.05.2013, 00:08
Если в контестере используется MSVS тогда я хз..
Может дело не в точности?
0
 Аватар для Ternsip
670 / 198 / 29
Регистрация: 10.05.2012
Сообщений: 595
12.05.2013, 12:50  [ТС]
lazybiz, может

Добавлено через 11 часов 51 минуту
upup

Добавлено через 48 минут
апь
0
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
12.05.2013, 14:37
Пока вижу только, что надо 12 знаков после запятой, а выводится 14. Из-за этого может не совпасть с ответом в младших цифрах (да и вообще это формат вывода, не удовлетворяющий условию, так что можно бы было сразу везде WA засчитывать).

Добавлено через 3 минуты
C++
1
if (ax > bx || (ax == bx && ay > by)) {
Тут сравнения без eps.
1
 Аватар для Ternsip
670 / 198 / 29
Регистрация: 10.05.2012
Сообщений: 595
13.05.2013, 09:18  [ТС]
Somebody, на 1 WA больше
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <iostream>
#include <set>
#include <vector>
#include <limits>
#include <stdio.h>
#include <string>
#include <queue>
#include <time.h>
 
using namespace std;
 
double eps = 1e-18;
 
bool comp(long double a, long double b){
    return (abs(a-b) < eps);
} 
 
void circle_line(long double a, long double b, long double c, long double r, long double x1, long double y1){
    long double x0 = -a*c/(a*a+b*b);
    long double y0 = -b*c/(a*a+b*b);
    if (c*c > r*r*(a*a+b*b)+eps){
        printf("There are no points!!!\n");
    }else if (comp(c*c, r*r*(a*a+b*b))) {
        printf("There are only 1 of them....\n");
        printf("%.12lf %.12lf\n", x0 + x1, y0 + y1);
    } else {
        printf("There are only 2 of them....\n");
        long double d = r*r - c*c/(a*a+b*b);
        long double mult = sqrt (d / (a*a+b*b));
        long double ax = x0 + b * mult;
        long double bx = x0 - b * mult;
        long double ay = y0 - a * mult;
        long double by = y0 + a * mult;
        if (ax > bx || (comp(ax, bx) && ay > by)) {
            swap(ax, bx);
            swap(ay, by);
        }
        printf("%.12lf %.12lf\n%.12lf %.12lf\n", ax + x1, ay + y1, bx + x1, by + y1);
    }
}
 
void circle_circle (long double x1, long double y1, long double r1, long double x2, long double y2, long double r2){
    if (comp(x1, x2) && comp(y1, y2)) {
        if (!comp(r1, r2)){
            printf("There are no points!!!\n");
        } else {
            printf("I can't count them - too many points :(\n");
        }
        return;
    }
    x2 -= x1;
    y2 -= y1;
    circle_line(- 2.0 * x2, - 2.0 * y2, x2*x2 + y2*y2 + r1*r1 - r2*r2, r1, x1, y1);
}
 
int main() {
    freopen("input.txt", "rt", stdin);
    freopen("output.txt", "wt", stdout);
    int t;
    cin >> t;
    while (t > 0) {
        long double x1, y1, r1, x2, y2, r2;
        scanf("%lf%lf%lf%lf%lf%lf", &x1, &y1, &r1, &x2, &y2, &r2);
        circle_circle(x1, y1, r1, x2, y2, r2);
        printf("\n");
        t--;
    }
    return 0;
}
Добавлено через 2 минуты
Somebody, а вот если ставлю %.15lf везде то по-прежнему 12 тестов, (на %.12lf было 11)

Добавлено через 18 часов 30 минут
Help
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
13.05.2013, 09:41
А зачем ты сам определяешь EPSILON: double eps = 1e-18; ?
Он определен в float.h, и у меня в GCC 4.7.3 он равен другому числу: 2.22045e-016
0
 Аватар для Ternsip
670 / 198 / 29
Регистрация: 10.05.2012
Сообщений: 595
13.05.2013, 15:55  [ТС]
lazybiz, мне так удобней, сути это не меняет. ошибка не в этом

Добавлено через 3 часа 47 минут
help

Добавлено через 41 секунду
Должен же быть какой то способ избавления от переполнения !!
0
2838 / 1647 / 254
Регистрация: 03.12.2007
Сообщений: 4,222
13.05.2013, 17:05
Универсальный и надёжный способ - сделать самому всю математику. Мантисса, порядок, все арифметические действия. Вопрос только в том, действительно ли задача тут на эту тему или просто ошибка в алгоритме, из-за которой где-то какие-то погрешности.
1
 Аватар для Ternsip
670 / 198 / 29
Регистрация: 10.05.2012
Сообщений: 595
13.05.2013, 17:21  [ТС]
Somebody, Забавное предложение, учту его, спасибо и на этом. Только я назвал бы это арифметикой, а задача исключительно на геометрию и не должна вызывать никаких сложностей в написании на с++, связанных с другими темами.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
13.05.2013, 17:21
Помогаю со студенческими работами здесь

Столкновение двух окружностей
Итак,я сталкиваю два шарика(но вообще их больше,массив). Какое-то время после старта программы все нормально,однако спустя некоторое...

Координаты пересечения двух окружностей
На вход даются целочисленные координаты двух окружностей и целочисленные их радиусы, которые не меньше 1 и не больше, чем 1000. Они...

Строка: Добавить в строковый класс функцию, которая создает строку, содержащую пересечение двух строк, то есть общие символы для двух строк.
Добавить в строковый класс функцию, которая создает строку, содержащую пересечение двух строк, то есть общие символы для двух строк....

Вычислить площадь пересечения двух окружностей
Здравствуйте) Может кто-нибудь сталкивался с написнием программы для вычисления площади пересечения двух кругов? помогите, пожалуйста...

Вводится значение двух радиусов окружностей
Помогите создать блок схему для задачи c пояснениями пожалуйста: Вводится значение двух радиусов окружностей R1,R2 и координаты точки...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru