Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
 
Ternsip
 Аватар для Ternsip
660 / 188 / 6
Регистрация: 10.05.2012
Сообщений: 595
11.05.2013, 22:57     Пересечение двух окружностей #1
Есть такая задачка.

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

В силу большой требуемой точности рекомендуется использовать более чем 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 минут
апп
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
castaway
Эксперт С++
4842 / 2981 / 367
Регистрация: 10.11.2010
Сообщений: 11,013
Записей в блоге: 10
Завершенные тесты: 1
11.05.2013, 23:04     Пересечение двух окружностей #2
...

Добавлено через 1 минуту
Цитата Сообщение от Ternsip Посмотреть сообщение
Вот тут сразу вопрос, это какие типы ? double 8 байтный, больше не знаю. Пишу на MVSC++ 2012
Ты же используешь long double !?
Ternsip
 Аватар для Ternsip
660 / 188 / 6
Регистрация: 10.05.2012
Сообщений: 595
11.05.2013, 23:54  [ТС]     Пересечение двух окружностей #3
lazybiz, а он в MVSC++ 2012 ничем не отличается от double
castaway
Эксперт С++
4842 / 2981 / 367
Регистрация: 10.11.2010
Сообщений: 11,013
Записей в блоге: 10
Завершенные тесты: 1
12.05.2013, 00:08     Пересечение двух окружностей #4
Если в контестере используется MSVS тогда я хз..
Может дело не в точности?
Ternsip
 Аватар для Ternsip
660 / 188 / 6
Регистрация: 10.05.2012
Сообщений: 595
12.05.2013, 12:50  [ТС]     Пересечение двух окружностей #5
lazybiz, может

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

Добавлено через 48 минут
апь
Somebody
2770 / 1583 / 141
Регистрация: 03.12.2007
Сообщений: 4,139
Завершенные тесты: 1
12.05.2013, 14:37     Пересечение двух окружностей #6
Пока вижу только, что надо 12 знаков после запятой, а выводится 14. Из-за этого может не совпасть с ответом в младших цифрах (да и вообще это формат вывода, не удовлетворяющий условию, так что можно бы было сразу везде WA засчитывать).

Добавлено через 3 минуты
C++
1
if (ax > bx || (ax == bx && ay > by)) {
Тут сравнения без eps.
Ternsip
 Аватар для Ternsip
660 / 188 / 6
Регистрация: 10.05.2012
Сообщений: 595
13.05.2013, 09:18  [ТС]     Пересечение двух окружностей #7
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
castaway
Эксперт С++
4842 / 2981 / 367
Регистрация: 10.11.2010
Сообщений: 11,013
Записей в блоге: 10
Завершенные тесты: 1
13.05.2013, 09:41     Пересечение двух окружностей #8
А зачем ты сам определяешь EPSILON: double eps = 1e-18; ?
Он определен в float.h, и у меня в GCC 4.7.3 он равен другому числу: 2.22045e-016
Ternsip
 Аватар для Ternsip
660 / 188 / 6
Регистрация: 10.05.2012
Сообщений: 595
13.05.2013, 15:55  [ТС]     Пересечение двух окружностей #9
lazybiz, мне так удобней, сути это не меняет. ошибка не в этом

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

Добавлено через 41 секунду
Должен же быть какой то способ избавления от переполнения !!
Somebody
2770 / 1583 / 141
Регистрация: 03.12.2007
Сообщений: 4,139
Завершенные тесты: 1
13.05.2013, 17:05     Пересечение двух окружностей #10
Универсальный и надёжный способ - сделать самому всю математику. Мантисса, порядок, все арифметические действия. Вопрос только в том, действительно ли задача тут на эту тему или просто ошибка в алгоритме, из-за которой где-то какие-то погрешности.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.05.2013, 17:21     Пересечение двух окружностей
Еще ссылки по теме:

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

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

Или воспользуйтесь поиском по форуму:
Ternsip
 Аватар для Ternsip
660 / 188 / 6
Регистрация: 10.05.2012
Сообщений: 595
13.05.2013, 17:21  [ТС]     Пересечение двух окружностей #11
Somebody, Забавное предложение, учту его, спасибо и на этом. Только я назвал бы это арифметикой, а задача исключительно на геометрию и не должна вызывать никаких сложностей в написании на с++, связанных с другими темами.
Yandex
Объявления
13.05.2013, 17:21     Пересечение двух окружностей
Ответ Создать тему

Метки
two circles intersection
Опции темы

Текущее время: 06:15. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru