From 6805423c7f4af20ddb5153ed5f29f4fb9b3fc8de Mon Sep 17 00:00:00 2001 From: SweetWeakness Date: Sat, 9 Nov 2019 00:42:31 +0300 Subject: [PATCH 1/3] 1st and 2nd module --- .gitignore | 1 + 1st module/mod1_a.cpp | 49 ++++++++++++ 1st module/mod1_b1.cpp | 45 +++++++++++ 2nd module/mod2_a.cpp | 125 ++++++++++++++++++++++++++++++ 2nd module/mod2_c.cpp | 170 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 390 insertions(+) create mode 100644 .gitignore create mode 100644 1st module/mod1_a.cpp create mode 100644 1st module/mod1_b1.cpp create mode 100644 2nd module/mod2_a.cpp create mode 100644 2nd module/mod2_c.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/1st module/mod1_a.cpp b/1st module/mod1_a.cpp new file mode 100644 index 0000000..1c2dbeb --- /dev/null +++ b/1st module/mod1_a.cpp @@ -0,0 +1,49 @@ +#include +#include + + +void prefix_function (std::string& s, std::vector& pi) { + int n = s.length(); + + for (int i=1; i 0 && s[i] != s[j]) + j = pi[j-1]; + + if (s[i] == s[j]) + ++j; + + pi[i] = j; + } +} + +int main() { + std::string s, pattern; + std::cin >> pattern; + std::cin >> s; + s = pattern + '#' + s; + int n = s.length(); + + std::vector pi (n, 0); + prefix_function(s, pi); + + for (int i=2*pattern.length(); i +#include + +const int alphabet = 26; + +char new_character(std::string& s, std::vector& pi, int index) { + std::vector available_symbols(alphabet, true); + + while (index > 0) { + index = pi[index - 1]; + available_symbols[s[index] - 'a'] = false; + } + + for (int i = 0; i < alphabet; ++i) { + if (available_symbols[i]) { + return 'a' + i; + } + } + +} + +std::string buildFromPrefix(std::vector& pi) { + std::string s = ""; + for(int i = 0; i pi; + int tmp; + + while(std::cin >> tmp){ + pi.push_back(tmp); + } + + std::cout << buildFromPrefix(pi); + + return 0; +} diff --git a/2nd module/mod2_a.cpp b/2nd module/mod2_a.cpp new file mode 100644 index 0000000..a783556 --- /dev/null +++ b/2nd module/mod2_a.cpp @@ -0,0 +1,125 @@ +/* + * Дана строка длины n. Найти количество ее различных подстрок. Используйте суффиксный массив. + * Построение суффиксного массива выполняйте за O(n log n). + * Вычисление количества различных подстрок выполняйте за O(n). +*/ +#include +#include + + +void sufix_array(std::string& s, int alphabet, std::vector& suffs) { + int n = s.size(); + int cnt_len = (n > alphabet ? n : alphabet); + std::vector cnt(cnt_len, 0); + std::vector classes(n, 0); + + for (int i = 0; i < n; ++i) { // карманная сортировка подсчетом + ++cnt[s[i] - '\0']; + } + for (int i = 1; i < alphabet; ++i) // считаем границы + cnt[i] += cnt[i-1]; + // suffs будет хранить индексы начал отсортированных подстрок текущей длины + for (int i = 0; i < n; ++i) { + suffs[--cnt[s[i] - '\0']] = i; + } + + int class_numb = 0; + char last_char = '$'; + // каждому суффиксу длины 1 сопоставляем класс + for (int i = 0; i < n; ++i) { + if (s[suffs[i]] != last_char){ + last_char = s[suffs[i]]; + ++class_numb; + } + classes[suffs[i]] = class_numb; + } + + + + + // нулевая итерация завершена + // сортируем подстроки длиной 2 * cur_len = 2^k + int cur_len = 1; + std::vector sorted_by2(n, 0); + std::vector new_classes(n, 0); + while (cur_len <= n){ + // сортируем по второй половине подстроки + for (int i = 0; i < n; ++i){ + sorted_by2[i] = (suffs[i] + n - cur_len) % n; + } + // сортируем по первой половине + // сортировка устойчивая, значит получим целиком отсортированные подстроки + for (int i = 0; i < cnt_len; ++i){ // обнуляем cnt + cnt[i] = 0; + } + + for (int i = 0; i < n; ++i){ + ++cnt[classes[sorted_by2[i]]]; + } + + for (int i = 1; i < cnt_len; ++i) // считаем границы + cnt[i] += cnt[i-1]; + + + for (int i = n - 1; i >= 0; --i){ + suffs[--cnt[classes[sorted_by2[i]]]] = sorted_by2[i]; + } + + class_numb = 0; + for (int i = 1; i < n; ++i){ + int mid1 = (suffs[i] + cur_len) % n; + int mid2 = (suffs[i - 1] + cur_len) % n; + if (classes[suffs[i]] != classes[suffs[i - 1]] or classes[mid1] != classes[mid2]) + ++class_numb; + new_classes[suffs[i]] = class_numb; + } + for (int i = 0; i < n; ++i){ + classes[i] = new_classes[i]; + } + cur_len *= 2; + } +} + +void lcp_array(std::string& s, std::vector& suffs, std::vector& lcp){ + int n = s.length(); + int k = 0; + std::vector pos(n); + for(int i = 0; i < n; ++i) pos[suffs[i]] = i; // pos = suffs^-1 + + for(int i = 0; i < n; ++i){ + if (k > 0) --k; + if (pos[i] == n - 1){ + k = 0; + lcp[n - 1] = -1; + }else{ + int j = suffs[pos[i] + 1]; + while ((i + k > j + k ? i + k : j + k) < n and s[i + k] == s[j + k]) + ++k; + lcp[pos[i]] = k; + } + } +} + +int find_substrings(std::string& s){ + s += "$"; + + std::vector p(s.size(), 0); + std::vector lcp(s.size(), 0); + sufix_array(s, 256, p); + lcp_array(s, p, lcp); + + int ans = 0; + for (int i = 0; i < s.size(); ++i) { + //std::cout << p[i] << "|" << lcp[i] << " \n"; + ans += s.size() - 1 - p[i] - lcp[i]; + } + return --ans; +} + +int main() { + std::string s; + std::cin >> s; + + std::cout << find_substrings(s); + return 0; +} diff --git a/2nd module/mod2_c.cpp b/2nd module/mod2_c.cpp new file mode 100644 index 0000000..f02c1f5 --- /dev/null +++ b/2nd module/mod2_c.cpp @@ -0,0 +1,170 @@ +/* + * Заданы две строки s, t и целое число k. + * Рассмотрим множество всех таких непустых строк, которые встречаются как подстроки в s и t одновременно. + * Найдите k-ую в лексикографическом порядке строку из этого множества. + * Полезная статья про сравнение указателей: https://stackoverflow.com/questions/9086372/how-to-compare-pointers. +*/ +#include +#include + + +void sufix_array(std::string& s, int alphabet, std::vector& suffs) { + int n = s.size(); + int cnt_len = (n > alphabet ? n : alphabet); + std::vector cnt(cnt_len, 0); + std::vector classes(n, 0); + + for (int i = 0; i < n; ++i) { // карманная сортировка подсчетом + ++cnt[s[i] - '\0']; + } + for (int i = 1; i < alphabet; ++i) // считаем границы + cnt[i] += cnt[i-1]; + // suffs будет хранить индексы начал отсортированных подстрок текущей длины + for (int i = 0; i < n; ++i) { + suffs[--cnt[s[i] - '\0']] = i; + } + + int class_numb = 0; + char last_char = '$'; + // каждому суффиксу длины 1 сопоставляем класс + for (int i = 0; i < n; ++i) { + if (s[suffs[i]] != last_char){ + last_char = s[suffs[i]]; + ++class_numb; + } + classes[suffs[i]] = class_numb; + } + + + + + // нулевая итерация завершена + // сортируем подстроки длиной 2 * cur_len = 2^k + int cur_len = 1; + std::vector sorted_by2(n, 0); + std::vector new_classes(n, 0); + while (cur_len <= n){ + // сортируем по второй половине подстроки + for (int i = 0; i < n; ++i){ + sorted_by2[i] = (suffs[i] + n - cur_len) % n; + } + // сортируем по первой половине + // сортировка устойчивая, значит получим целиком отсортированные подстроки + for (int i = 0; i < cnt_len; ++i){ // обнуляем cnt + cnt[i] = 0; + } + + for (int i = 0; i < n; ++i){ + ++cnt[classes[sorted_by2[i]]]; + } + + for (int i = 1; i < cnt_len; ++i) // считаем границы + cnt[i] += cnt[i-1]; + + + for (int i = n - 1; i >= 0; --i){ + suffs[--cnt[classes[sorted_by2[i]]]] = sorted_by2[i]; + } + + class_numb = 0; + for (int i = 1; i < n; ++i){ + int mid1 = (suffs[i] + cur_len) % n; + int mid2 = (suffs[i - 1] + cur_len) % n; + if (classes[suffs[i]] != classes[suffs[i - 1]] or classes[mid1] != classes[mid2]) + ++class_numb; + new_classes[suffs[i]] = class_numb; + } + for (int i = 0; i < n; ++i){ + classes[i] = new_classes[i]; + } + cur_len *= 2; + } +} + +void lcp_array(std::string& s, std::vector& suffs, std::vector& lcp){ + int n = s.length(); + int k = 0; + std::vector pos(n); + for(int i = 0; i < n; ++i) pos[suffs[i]] = i; // pos = suffs^-1 + + for(int i = 0; i < n; ++i){ + if (k > 0) --k; + if (pos[i] == n - 1){ + k = 0; + lcp[n - 1] = -1; + }else{ + int j = suffs[pos[i] + 1]; + while ((i + k > j + k ? i + k : j + k) < n and s[i + k] == s[j + k]) + ++k; + lcp[pos[i]] = k; + } + } + + for(int i = n - 1; i > 0; --i){ + lcp[i] = lcp[i - 1]; + } + lcp[0] = -1; +} + +bool is_changed(std::vector& p, int i, int pivot){ + return (p[i] < pivot && p[i - 1] > pivot) || + (p[i] > pivot && p[i - 1] < pivot); +} + + +std::string find_k_substring(std::string& s, std::string& l, int64_t k){ + int old_s_size = s.size(); + s = s + "#" + l + "$"; + + std::vector p(s.size(), 0); + std::vector lcp(s.size(), 0); + sufix_array(s, 256, p); + lcp_array(s, p, lcp); + + for (int i = 0; i < s.size(); ++i) { + //std::cout << p[i] << "|" << lcp[i] << " \n"; + } + + int lcp_old = 0; + std::string ans; + + for (int i = 1; i < s.size(); ++i){ + if (is_changed(p, i, old_s_size)){ + //std::cout << p[i - 1] << " comp with " << p[i] << " " << "(" << lcp[i] << ") " << k << "\n"; + if (lcp_old + k > lcp[i]) { + if (lcp[i] >= lcp_old) { + k -= lcp[i] - lcp_old; + } + lcp_old = lcp[i]; + + }else{ + for (int j = p[i]; j < lcp_old + k + p[i]; ++j) { + std::cout << s[j]; + } + + k = 0; + break; + } + } + if (lcp[i] < lcp_old){ + lcp_old = lcp[i]; + } + } + + if (k > 0) + ans = "-1"; + + return ans; +} + +int main() { + std::string s, l; + int64_t k; + std::cin >> s; + std::cin >> l; + std::cin >> k; + + + std::cout << find_k_substring(s, l, k); + return 0; +} From 94412821b10312ef5cd1f0432a8e8c57ee02843b Mon Sep 17 00:00:00 2001 From: SweetWeakness Date: Thu, 21 Nov 2019 00:03:48 +0300 Subject: [PATCH 2/3] 3d module (a) --- 1st module/mod1_a.cpp | 49 ------------ 1st module/mod1_b1.cpp | 45 ----------- 2nd module/mod2_a.cpp | 125 ------------------------------ 2nd module/mod2_c.cpp | 170 ----------------------------------------- mod3_a.cpp | 102 +++++++++++++++++++++++++ 5 files changed, 102 insertions(+), 389 deletions(-) delete mode 100644 1st module/mod1_a.cpp delete mode 100644 1st module/mod1_b1.cpp delete mode 100644 2nd module/mod2_a.cpp delete mode 100644 2nd module/mod2_c.cpp create mode 100644 mod3_a.cpp diff --git a/1st module/mod1_a.cpp b/1st module/mod1_a.cpp deleted file mode 100644 index 1c2dbeb..0000000 --- a/1st module/mod1_a.cpp +++ /dev/null @@ -1,49 +0,0 @@ -#include -#include - - -void prefix_function (std::string& s, std::vector& pi) { - int n = s.length(); - - for (int i=1; i 0 && s[i] != s[j]) - j = pi[j-1]; - - if (s[i] == s[j]) - ++j; - - pi[i] = j; - } -} - -int main() { - std::string s, pattern; - std::cin >> pattern; - std::cin >> s; - s = pattern + '#' + s; - int n = s.length(); - - std::vector pi (n, 0); - prefix_function(s, pi); - - for (int i=2*pattern.length(); i -#include - -const int alphabet = 26; - -char new_character(std::string& s, std::vector& pi, int index) { - std::vector available_symbols(alphabet, true); - - while (index > 0) { - index = pi[index - 1]; - available_symbols[s[index] - 'a'] = false; - } - - for (int i = 0; i < alphabet; ++i) { - if (available_symbols[i]) { - return 'a' + i; - } - } - -} - -std::string buildFromPrefix(std::vector& pi) { - std::string s = ""; - for(int i = 0; i pi; - int tmp; - - while(std::cin >> tmp){ - pi.push_back(tmp); - } - - std::cout << buildFromPrefix(pi); - - return 0; -} diff --git a/2nd module/mod2_a.cpp b/2nd module/mod2_a.cpp deleted file mode 100644 index a783556..0000000 --- a/2nd module/mod2_a.cpp +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Дана строка длины n. Найти количество ее различных подстрок. Используйте суффиксный массив. - * Построение суффиксного массива выполняйте за O(n log n). - * Вычисление количества различных подстрок выполняйте за O(n). -*/ -#include -#include - - -void sufix_array(std::string& s, int alphabet, std::vector& suffs) { - int n = s.size(); - int cnt_len = (n > alphabet ? n : alphabet); - std::vector cnt(cnt_len, 0); - std::vector classes(n, 0); - - for (int i = 0; i < n; ++i) { // карманная сортировка подсчетом - ++cnt[s[i] - '\0']; - } - for (int i = 1; i < alphabet; ++i) // считаем границы - cnt[i] += cnt[i-1]; - // suffs будет хранить индексы начал отсортированных подстрок текущей длины - for (int i = 0; i < n; ++i) { - suffs[--cnt[s[i] - '\0']] = i; - } - - int class_numb = 0; - char last_char = '$'; - // каждому суффиксу длины 1 сопоставляем класс - for (int i = 0; i < n; ++i) { - if (s[suffs[i]] != last_char){ - last_char = s[suffs[i]]; - ++class_numb; - } - classes[suffs[i]] = class_numb; - } - - - - - // нулевая итерация завершена - // сортируем подстроки длиной 2 * cur_len = 2^k - int cur_len = 1; - std::vector sorted_by2(n, 0); - std::vector new_classes(n, 0); - while (cur_len <= n){ - // сортируем по второй половине подстроки - for (int i = 0; i < n; ++i){ - sorted_by2[i] = (suffs[i] + n - cur_len) % n; - } - // сортируем по первой половине - // сортировка устойчивая, значит получим целиком отсортированные подстроки - for (int i = 0; i < cnt_len; ++i){ // обнуляем cnt - cnt[i] = 0; - } - - for (int i = 0; i < n; ++i){ - ++cnt[classes[sorted_by2[i]]]; - } - - for (int i = 1; i < cnt_len; ++i) // считаем границы - cnt[i] += cnt[i-1]; - - - for (int i = n - 1; i >= 0; --i){ - suffs[--cnt[classes[sorted_by2[i]]]] = sorted_by2[i]; - } - - class_numb = 0; - for (int i = 1; i < n; ++i){ - int mid1 = (suffs[i] + cur_len) % n; - int mid2 = (suffs[i - 1] + cur_len) % n; - if (classes[suffs[i]] != classes[suffs[i - 1]] or classes[mid1] != classes[mid2]) - ++class_numb; - new_classes[suffs[i]] = class_numb; - } - for (int i = 0; i < n; ++i){ - classes[i] = new_classes[i]; - } - cur_len *= 2; - } -} - -void lcp_array(std::string& s, std::vector& suffs, std::vector& lcp){ - int n = s.length(); - int k = 0; - std::vector pos(n); - for(int i = 0; i < n; ++i) pos[suffs[i]] = i; // pos = suffs^-1 - - for(int i = 0; i < n; ++i){ - if (k > 0) --k; - if (pos[i] == n - 1){ - k = 0; - lcp[n - 1] = -1; - }else{ - int j = suffs[pos[i] + 1]; - while ((i + k > j + k ? i + k : j + k) < n and s[i + k] == s[j + k]) - ++k; - lcp[pos[i]] = k; - } - } -} - -int find_substrings(std::string& s){ - s += "$"; - - std::vector p(s.size(), 0); - std::vector lcp(s.size(), 0); - sufix_array(s, 256, p); - lcp_array(s, p, lcp); - - int ans = 0; - for (int i = 0; i < s.size(); ++i) { - //std::cout << p[i] << "|" << lcp[i] << " \n"; - ans += s.size() - 1 - p[i] - lcp[i]; - } - return --ans; -} - -int main() { - std::string s; - std::cin >> s; - - std::cout << find_substrings(s); - return 0; -} diff --git a/2nd module/mod2_c.cpp b/2nd module/mod2_c.cpp deleted file mode 100644 index f02c1f5..0000000 --- a/2nd module/mod2_c.cpp +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Заданы две строки s, t и целое число k. - * Рассмотрим множество всех таких непустых строк, которые встречаются как подстроки в s и t одновременно. - * Найдите k-ую в лексикографическом порядке строку из этого множества. - * Полезная статья про сравнение указателей: https://stackoverflow.com/questions/9086372/how-to-compare-pointers. -*/ -#include -#include - - -void sufix_array(std::string& s, int alphabet, std::vector& suffs) { - int n = s.size(); - int cnt_len = (n > alphabet ? n : alphabet); - std::vector cnt(cnt_len, 0); - std::vector classes(n, 0); - - for (int i = 0; i < n; ++i) { // карманная сортировка подсчетом - ++cnt[s[i] - '\0']; - } - for (int i = 1; i < alphabet; ++i) // считаем границы - cnt[i] += cnt[i-1]; - // suffs будет хранить индексы начал отсортированных подстрок текущей длины - for (int i = 0; i < n; ++i) { - suffs[--cnt[s[i] - '\0']] = i; - } - - int class_numb = 0; - char last_char = '$'; - // каждому суффиксу длины 1 сопоставляем класс - for (int i = 0; i < n; ++i) { - if (s[suffs[i]] != last_char){ - last_char = s[suffs[i]]; - ++class_numb; - } - classes[suffs[i]] = class_numb; - } - - - - - // нулевая итерация завершена - // сортируем подстроки длиной 2 * cur_len = 2^k - int cur_len = 1; - std::vector sorted_by2(n, 0); - std::vector new_classes(n, 0); - while (cur_len <= n){ - // сортируем по второй половине подстроки - for (int i = 0; i < n; ++i){ - sorted_by2[i] = (suffs[i] + n - cur_len) % n; - } - // сортируем по первой половине - // сортировка устойчивая, значит получим целиком отсортированные подстроки - for (int i = 0; i < cnt_len; ++i){ // обнуляем cnt - cnt[i] = 0; - } - - for (int i = 0; i < n; ++i){ - ++cnt[classes[sorted_by2[i]]]; - } - - for (int i = 1; i < cnt_len; ++i) // считаем границы - cnt[i] += cnt[i-1]; - - - for (int i = n - 1; i >= 0; --i){ - suffs[--cnt[classes[sorted_by2[i]]]] = sorted_by2[i]; - } - - class_numb = 0; - for (int i = 1; i < n; ++i){ - int mid1 = (suffs[i] + cur_len) % n; - int mid2 = (suffs[i - 1] + cur_len) % n; - if (classes[suffs[i]] != classes[suffs[i - 1]] or classes[mid1] != classes[mid2]) - ++class_numb; - new_classes[suffs[i]] = class_numb; - } - for (int i = 0; i < n; ++i){ - classes[i] = new_classes[i]; - } - cur_len *= 2; - } -} - -void lcp_array(std::string& s, std::vector& suffs, std::vector& lcp){ - int n = s.length(); - int k = 0; - std::vector pos(n); - for(int i = 0; i < n; ++i) pos[suffs[i]] = i; // pos = suffs^-1 - - for(int i = 0; i < n; ++i){ - if (k > 0) --k; - if (pos[i] == n - 1){ - k = 0; - lcp[n - 1] = -1; - }else{ - int j = suffs[pos[i] + 1]; - while ((i + k > j + k ? i + k : j + k) < n and s[i + k] == s[j + k]) - ++k; - lcp[pos[i]] = k; - } - } - - for(int i = n - 1; i > 0; --i){ - lcp[i] = lcp[i - 1]; - } - lcp[0] = -1; -} - -bool is_changed(std::vector& p, int i, int pivot){ - return (p[i] < pivot && p[i - 1] > pivot) || - (p[i] > pivot && p[i - 1] < pivot); -} - - -std::string find_k_substring(std::string& s, std::string& l, int64_t k){ - int old_s_size = s.size(); - s = s + "#" + l + "$"; - - std::vector p(s.size(), 0); - std::vector lcp(s.size(), 0); - sufix_array(s, 256, p); - lcp_array(s, p, lcp); - - for (int i = 0; i < s.size(); ++i) { - //std::cout << p[i] << "|" << lcp[i] << " \n"; - } - - int lcp_old = 0; - std::string ans; - - for (int i = 1; i < s.size(); ++i){ - if (is_changed(p, i, old_s_size)){ - //std::cout << p[i - 1] << " comp with " << p[i] << " " << "(" << lcp[i] << ") " << k << "\n"; - if (lcp_old + k > lcp[i]) { - if (lcp[i] >= lcp_old) { - k -= lcp[i] - lcp_old; - } - lcp_old = lcp[i]; - - }else{ - for (int j = p[i]; j < lcp_old + k + p[i]; ++j) { - std::cout << s[j]; - } - - k = 0; - break; - } - } - if (lcp[i] < lcp_old){ - lcp_old = lcp[i]; - } - } - - if (k > 0) - ans = "-1"; - - return ans; -} - -int main() { - std::string s, l; - int64_t k; - std::cin >> s; - std::cin >> l; - std::cin >> k; - - - std::cout << find_k_substring(s, l, k); - return 0; -} diff --git a/mod3_a.cpp b/mod3_a.cpp new file mode 100644 index 0000000..3c1c0a4 --- /dev/null +++ b/mod3_a.cpp @@ -0,0 +1,102 @@ +/* + * Даны два отрезка в пространстве (x1, y1, z1) - (x2, y2, z2) и (x3, y3, z3) - (x4, y4, z4). + * Найдите расстояние между отрезками. + * + * */ +#include +#include +#include + + + +struct Point { + double x, y, z; + + Point (double a, double b, double c) : x (a), y (b), z (c) {} + + Point () : x (0), y (0), z (0) {} + + // расстояние между точками + double getDistance(const Point& p) { + return sqrt(pow((p.x - this->x), 2) + pow((p.y - this->y), 2) + pow((p.z - this->z), 2)); + } + + Point operator+=(const Point& p) { + this->x += p.x; + this->y += p.y; + this->z += p.z; + return *this; + } + + Point operator/=(const double mult) { + this->x /= mult; + this->y /= mult; + this->z /= mult; + return *this; + } + + double getDistanceToSegment(Point l, Point r, double eps = 0.0000001) { + Point a, b; + + while (l.getDistance(r) > eps) { + a = Point (l.x * 2 + r.x, l.y * 2 + r.y, l.z * 2 + r.z) /= 3; + b = Point (l.x + r.x * 2, l.y + r.y * 2, l.z + r.z * 2) /= 3; + + if (this->getDistance(a) < this->getDistance(b)) { + r = b; + } else { + l = a; + } + } + + return this->getDistance((l += r) /= 2); + } +}; + + +struct Segment { + Point one, two; + + Segment (const Point& a, const Point& b) { + one = a; + two = b; + } + + double getDistanceToSegment(const Segment& seg, const double eps = 0.0000001) { + Point a, b; + Point l = this->one; + Point r = this->two; + + while (l.getDistance(r) > eps) { + a = Point (l.x * 2 + r.x, l.y * 2 + r.y, l.z * 2 + r.z) /= 3; + b = Point (l.x + r.x * 2, l.y + r.y * 2, l.z + r.z * 2) /= 3; + + if (a.getDistanceToSegment(seg.one, seg.two) < b.getDistanceToSegment(seg.one, seg.two)) { + r = b; + } else { + l = a; + } + } + + return ((l += r) /= 2).getDistanceToSegment(seg.one, seg.two); + } +}; + + +int main() { + int x, y, z; + + std::cin >> x >> y >> z; + Point a (x, y, z); + std::cin >> x >> y >> z; + Point b (x, y, z); + std::cin >> x >> y >> z; + Point c (x, y, z); + std::cin >> x >> y >> z; + Point d (x, y, z); + + Segment seg (c, d); + + printf("%.9lf", Segment(a, b).getDistanceToSegment(seg)); + return 0; +} From 5d4d3cbaf276a69e6e53e969364aabaf4c8925b9 Mon Sep 17 00:00:00 2001 From: SweetWeakness Date: Sun, 8 Dec 2019 16:47:13 +0300 Subject: [PATCH 3/3] =?UTF-8?q?=D0=B4=D0=BE=D0=B4=D0=B5=D0=BB=D0=B0=D0=BB?= =?UTF-8?q?=20=D0=B4=D0=BE=20=D0=BA=D0=BE=D0=BD=D1=86=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- geometry.cpp | 49 ++++++++++++++++++++++++++++ geometry.h | 34 ++++++++++++++++++++ mod3_a.cpp | 83 ++++-------------------------------------------- ternary_search.h | 20 ++++++++++++ 4 files changed, 109 insertions(+), 77 deletions(-) create mode 100644 geometry.cpp create mode 100644 geometry.h create mode 100644 ternary_search.h diff --git a/geometry.cpp b/geometry.cpp new file mode 100644 index 0000000..11e2cb1 --- /dev/null +++ b/geometry.cpp @@ -0,0 +1,49 @@ +#include "geometry.h" +#include +#include "ternary_search.h" + +Point::Point(double a, double b, double c) : x (a), y (b), z (c) {} + +Point::Point() : x (0), y (0), z (0) {} + +Segment::Segment (const Point& a, const Point& b) { + one = a; + two = b; +} + + +// расстояние между точками +const double getDistance(const Point& one, const Point& two) { + return sqrt(pow((one.x - two.x), 2) + pow((one.y - two.y), 2) + pow((one.z - two.z), 2)); +} + +Point operator+(const Point& one, const Point& two) { + return Point(one.x + two.x, one.y + two.y, one.z + two.z); +} + +Point operator*(const Point& p, double mult) { + return Point(p.x * mult, p.y * mult, p.z * mult); +} + +Point operator/(const Point& p, double mult) { + return Point(p.x / mult, p.y / mult, p.z / mult); +} + +double getDistancePointToSegment(const Point& p, const Segment& seg, double eps) { + auto func = [&p](const Point& p_to) { + return getDistance(p_to, p); + }; + // 1ый аргумент - точка, до которой кратчайшее растояние от p, 2ой - p + Point least_p_in_seg = ternarySearchMin(seg.one, seg.two, func, getDistance, eps); + return getDistance(least_p_in_seg, p); +} + + +double getDistanceSegmentToSegment(const Segment& seg1, const Segment& seg2, double eps) { + auto func = [&seg2](const Point& p_to) { + return getDistancePointToSegment(p_to, seg2); + }; + // 1ый аргумент - точка, до которой кратчайшее растояние от p, 2ой - p + Point x = ternarySearchMin(seg1.one, seg1.two, func, getDistance, eps); + return getDistancePointToSegment(x, seg2); +} diff --git a/geometry.h b/geometry.h new file mode 100644 index 0000000..347c2b8 --- /dev/null +++ b/geometry.h @@ -0,0 +1,34 @@ +#ifndef INC_3TERM_CONTESTS_GEOMETRY_H +#define INC_3TERM_CONTESTS_GEOMETRY_H + + +struct Point { + double x, y, z; + + Point (double a, double b, double c); + + Point (); +}; + +struct Segment { + Point one, two; + + Segment (const Point& a, const Point& b); +}; + + +// расстояние между точками +const double getDistance(const Point& one, const Point& two); + +Point operator+(const Point& one, const Point& two); + +Point operator*(const Point& p, double mult); + +Point operator/(const Point& p, double mult); + +double getDistancePointToSegment(const Point& p, const Segment& seg, double eps = 0.0000001); + +double getDistanceSegmentToSegment(const Segment& seg1, const Segment& seg2, double eps = 0.0000001); + + +#endif //INC_3TERM_CONTESTS_GEOMETRY_H diff --git a/mod3_a.cpp b/mod3_a.cpp index 3c1c0a4..8899794 100644 --- a/mod3_a.cpp +++ b/mod3_a.cpp @@ -3,84 +3,12 @@ * Найдите расстояние между отрезками. * * */ + + #include #include #include - - - -struct Point { - double x, y, z; - - Point (double a, double b, double c) : x (a), y (b), z (c) {} - - Point () : x (0), y (0), z (0) {} - - // расстояние между точками - double getDistance(const Point& p) { - return sqrt(pow((p.x - this->x), 2) + pow((p.y - this->y), 2) + pow((p.z - this->z), 2)); - } - - Point operator+=(const Point& p) { - this->x += p.x; - this->y += p.y; - this->z += p.z; - return *this; - } - - Point operator/=(const double mult) { - this->x /= mult; - this->y /= mult; - this->z /= mult; - return *this; - } - - double getDistanceToSegment(Point l, Point r, double eps = 0.0000001) { - Point a, b; - - while (l.getDistance(r) > eps) { - a = Point (l.x * 2 + r.x, l.y * 2 + r.y, l.z * 2 + r.z) /= 3; - b = Point (l.x + r.x * 2, l.y + r.y * 2, l.z + r.z * 2) /= 3; - - if (this->getDistance(a) < this->getDistance(b)) { - r = b; - } else { - l = a; - } - } - - return this->getDistance((l += r) /= 2); - } -}; - - -struct Segment { - Point one, two; - - Segment (const Point& a, const Point& b) { - one = a; - two = b; - } - - double getDistanceToSegment(const Segment& seg, const double eps = 0.0000001) { - Point a, b; - Point l = this->one; - Point r = this->two; - - while (l.getDistance(r) > eps) { - a = Point (l.x * 2 + r.x, l.y * 2 + r.y, l.z * 2 + r.z) /= 3; - b = Point (l.x + r.x * 2, l.y + r.y * 2, l.z + r.z * 2) /= 3; - - if (a.getDistanceToSegment(seg.one, seg.two) < b.getDistanceToSegment(seg.one, seg.two)) { - r = b; - } else { - l = a; - } - } - - return ((l += r) /= 2).getDistanceToSegment(seg.one, seg.two); - } -}; +#include "geometry.h" int main() { @@ -95,8 +23,9 @@ int main() { std::cin >> x >> y >> z; Point d (x, y, z); - Segment seg (c, d); + Segment seg1 (c, d); + Segment seg2 (a, b); - printf("%.9lf", Segment(a, b).getDistanceToSegment(seg)); + printf("%.9lf", getDistanceSegmentToSegment(seg1, seg2)); return 0; } diff --git a/ternary_search.h b/ternary_search.h new file mode 100644 index 0000000..965c2a6 --- /dev/null +++ b/ternary_search.h @@ -0,0 +1,20 @@ +#ifndef INC_3TERM_CONTESTS_TERNARY_SEARCH_H +#define INC_3TERM_CONTESTS_TERNARY_SEARCH_H + + +template +T ternarySearchMin(T left, T right, Func f, const double (*getDistance)(const T&, const T&), double eps = 0.0000001) { + while (getDistance(left, right) > eps) { + T a = (left * 2 + right) / 3; + T b = (left + right * 2) / 3; + if (f(a) < f(b)) { + right = b; + } else { + left = a; + } + } + return (left + right) / 2; +} + + +#endif //INC_3TERM_CONTESTS_TERNARY_SEARCH_H