Условие задачи:
Найти площадь полной поверхности параллелепипеда три стороны которого образованы векторами [latex] \overrightarrow{a}=(a_x,a_y,a_z), \overrightarrow{b}=(b_x,b_y,b_z) [/latex] и [latex]\overrightarrow{c}=(c_x,c_y,c_z)[/latex].
Входные данные:
Координаты векторов [latex] \overrightarrow{a}, \overrightarrow{b}[/latex] и [latex] \overrightarrow{c} [/latex].
Выходные данные:
Площадь полной поверхности параллелепипеда.
Тесты
№ | Входные данные | Выходные данные |
1 | -5.6 8.3 -7.1 2 11 -8 2.1 1 3.3 | 389.28894739406866 |
2 | 1 2 3 4 5 6 7 8 9 | 58.787753826796276 |
3 | -9 2 4 -3 5 1 -6 7 8 | 305.5334243147188 |
4 | 1 1 1 1 1 1 1 1 1 | 0.0 |
5 | 0 0 1 0 1 0 1 0 0 | 6.0 |
6 | 0 0 0 1 0 0 0 0 1 | 2.0 |
7 | 1 0 0 0 0 1 0 0 1 | 2.0 |
Код на C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <iostream> #include <cmath> #include <iomanip> using namespace std; double s1(double a1, double a2, double a3, double b1, double b2, double b3) //Создаем функцию для нахождения стороны параллелепипеда { return sqrt((a2*b3 - a3*b2)*(a2*b3 - a3*b2) + (a3*b1 - a1*b3)*(a3*b1 - a1*b3) + (a1*b2 - a2*b1)*(a1*b2 - a2*b1)); //Модуль векторного произведения } int main() { double ax, ay, az, bx, by, bz, cx, cy, cz, sab, sac, sbc, s; cin >> ax >> ay >> az >> bx >> by >> bz >> cx >> cy >> cz; sab = s1(ax, ay, az, bx, by, bz); //Поочередно вызываем функцию для каждой стороны sac = s1(ax, ay, az, cx, cy, cz); sbc = s1(bx, by, bz, cx, cy, cz); if ((ax == bx && ay == by && az == bz) || (ax == cx && ay == cy && az==cz) || (bx == cx && by == cy && bz == cz)) s = sab + sac + sbc; //Конечная формула площади полной поверхности параллелепипеда else s = (sab + sac + sbc)*2; cout << setprecision(15) << s; return 0; } |
Код на Java
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 |
import java.util.*; import java.lang.*; import java.io.*; class Ideone { static double s1(double a1, double a2, double a3, double b1, double b2, double b3) //Создаем функцию для нахождения стороны параллелепипеда { return Math.sqrt((a2*b3 - a3*b2)*(a2*b3 - a3*b2) + (a3*b1 - a1*b3)*(a3*b1 - a1*b3) + (a1*b2 - a2*b1)*(a1*b2 - a2*b1)); //Модуль векторного произведения } public static void main (String[] args) throws java.lang.Exception { Scanner in = new Scanner(System.in); double ax, ay, az, bx, by, bz, cx, cy, cz, sab, sac, sbc, s; ax = in.nextDouble(); ay = in.nextDouble(); az = in.nextDouble(); bx = in.nextDouble(); by = in.nextDouble(); bz = in.nextDouble(); cx = in.nextDouble(); cy = in.nextDouble(); cz = in.nextDouble(); sab = s1(ax, ay, az, bx, by, bz); //Поочередно вызываем функцию для каждой стороны sac = s1(ax, ay, az, cx, cy, cz); sbc = s1(bx, by, bz, cx, cy, cz); if ((ax == bx && ay == by && az == bz) || (ax == cx && ay == cy && az == cz) || (bx == cx && by == cy && bz == cz)) s = sab + sac + sbc; //Конечная формула площади полной поверхности параллелепипеда else s = (sab + sac + sbc)*2; System.out.println(s); } } |
Алгоритм
По определению Параллелепипед — призма, основанием которой служит параллелограмм, или (равносильно) многогранник, у которого шесть граней и каждая из них — параллелограмм.
Для решения данной задачи нужно сперва найти площади трёх сторон (параллелограммов) данного параллелепипеда. Воспользуемся геометрическим смыслом векторного произведения:
- Модуль векторного произведения [latex] [\overrightarrow{a},\overrightarrow{b}] [/latex] равняется площади S параллелограмма, построенного на приведённых к общему началу векторах [latex]\overrightarrow { a }[/latex] и [latex]\overrightarrow { b } [/latex]
Рассчитаем площадь каждого параллелограмма по формуле [latex] \left|\left[ \overrightarrow { a } , \overrightarrow { b } \right]\right| =
\left|(a_{ y }b_{ z }-a_{ z }b_{ y }, a_{ z }b_{ x }-a_{ x }b_{ z }, a_{ x }b_{ y }-a_{ y }b_{ x })\right|[/latex].
Найдя все три стороны, получим площадь полной поверхности параллелепипеда по формуле
[latex] S=2*(S_1+S_2+S_3) [/latex], где [latex] S_n [/latex] — площадь стороны параллелепипеда.
Ссылки:
Условие задачи ML31.
Работающая версия программы на языке C++.
Работающая версия программы на языке Java.
Геометрические свойства векторного произведения.
Хорошо. Молодец.
Есть несколько замечаний, которые будет легко поправить.
— Для записи в тригонометрических функций нужно писать так \sin x, а не sin x.
— Добавьте, пожалуйста очевидный тест 0 0 1 0 1 0 1 0 0.
А вот теперь замечание с которым нужно будет повозиться:
— Добавьте тест, где все три вектора совпадают, например, 1 1 1 1 1 1 1 1 1.
— Добавьте тест, в котором один из векторов нулевой, например, 0 0 0 1 0 0 0 0 1
— Добавьте тест, где два вектора совпадают, например, 1 0 0 0 0 1 0 0 1
Конечно, это всё вырожденные случаи, но для них вполне ясно, какая будет площадь поверхности и программа должна её вычислять.
Здравствуйте.
Переделал код для частных случаев. Исправил формулы. Добавил тесты.
— Не геометрическое свойство, а геометрический смысл векторного произведения.
— Вы использовали (и дали ссылку) на формулу, но у Вас заданы координаты векторов в декартовой системе координат, а не длина и угол между ними. Для этого случая больше подходит формула, например, из этой статьи. Это должно позволить обойтись без каких-либо ветвлений.
— В текущем варианте нужно расставить правильно отступы. Но я бы советовал написать функцию вычисления модуля векторного произведения и трижды её вызвал. И без ветвлений. Зачем они?
Здравствуйте.
— Исправил лексические ошибки в тексте.
— Переделал код. Убрал ветвления. Написал функцию для нахождения модуля векторного произведения.
— Полностью изменил алгоритм решения, как Вы советовали.
— Изменил гиперссылки.
Возник вопрос по поводу 7 теста. Мне кажется, для него необходимо добавить ветвление, т.к. программа должна выводить «2» вместо «4». Для всех остальных тестов программа работает правильно. Проверял здесь , находя каждую сторону отдельно.
Еще раз спасибо за помощь.
Вы про вырожденный случай? Думаю тут не будет проблемы — всё равно в пространстве у этого объекта есть две стороны с противоположными значениями нормали. Проще говоря, чтобы закрасить лист бумаги нужна краска для обоих сторон.
Нужно сделать правильны отступы.
Верно. Но в данном случае два вектора совпадают и перпендикулярны третьему вектору. Тогда у нас плоская фигура с верхней частью «листа», равной 1 и нижней частью, также равной 1. Тогда площадь будет 2, но никак не 4. Т.е. у нас будет квадрат со стороной 1.
Отступы исправил.
По тесту №7 Вы правы. Действительно, ответ должен быть 2, а не 4. Действительно, тернарная операция понадобится для случая двух совпадающих векторов.
Добавил тернарную операцию.
Исправил ответ в тесте №7.
Добавил код на Java. Изменил тесты и ссылки.
Дан, посмотрите на Википедии, что такое ключевые слова. Название языков программирования никак не характеризуют задачу и алгоритм решения.
Учту на будущее. Добавил ключевые слова. Сделал код немного читабельнее, заменив тернарную операцию условной и изменив отступы. Добавил точность вывода в коде на C++.