![]() |
|
Модераторы: Alx, Fixin |
![]()
|
|
| Fixin |
|
|||
![]() Ёжик ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1357 Регистрация: 6.1.2004 Репутация: нет Всего: 18 |
Задано алгебраическое выражение, составленное из неотрицательных вещественных чисел и знаков операций +, - и *. Необходимо расставить в этом выражении скобки так, чтобы его значение стало максимально возможным.
Технические требования Входной файл: INPUT1.TXT Выходной файл: OUTPUT1.TXT Формат входных данных В первой строке входного файла INPUT1.TXT записано исходное выражение длиной не более 250 символов. Внутри чисел пробелы не допускаются. Выражение содержит не более 50 чисел, каждое из которых лежит в диапазоне от 0 до 10 в 6 степени. Формат выходных данных Выходной файл OUTPUT1.TXT должен содержать две строки. В первой должно находиться максимально возможное после расстановки скобок значение полученного выражения, во второй строке - само это выражение. Если вариантов решения задачи несколько, нужно выдать любой из них. Пример файла входных данных 1+2-3.0*4 Пример файла выходных данных ((1+2)-3)*4 Вобщем парсингом мудрить думаю муторно для олимпиады, а что еще можете предложить? Это сообщение отредактировал(а) Fixin - 10.2.2005, 19:11 |
|||
|
||||
| Sardar |
|
||||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 1 Всего: 317 |
Что то я не понял примера -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
||||
|
|||||
| maxim1000 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 2 Всего: 110 |
если расставить скобки по-другому, получится меньший результат (по крайней мере, мне так показалось...) -------------------- qqq |
|||
|
||||
| Fixin |
|
|||
![]() Ёжик ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1357 Регистрация: 6.1.2004 Репутация: нет Всего: 18 |
Пример не проверял. Дело не в том. Как решать-то? Это первая задача и пяти. Остальные сделал. Олимпиада областная. Мне тоже кажется, что можно и отрицательное получить... но не проверял.
Добавлено @ 19:38 Тьфу, ошибся! Там максимум нужен!!! |
|||
|
||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 1 Всего: 317 |
Так тоже ноль будет: (1+(2-3))*4 Извиняюсь за глупость, но что если перебрать все возможные варианты... Медленно, но верно Строим все возможные деревья, начиная с обьеденения листьев, затем узлов. С каждой новой вариацией копируем дерево и пускаем его по альтернативному варианту. -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| Akina |
|
|||
|
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 2 Всего: 454 |
Только перебор.
-------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
| maxim1000 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 2 Всего: 110 |
можно покрутить в таком направлении:
как бы мы не расставили скобки, какое-то действие будет выполнено последним выделим его выбор в отдельную часть перебора т.е. сначала сделаем простой цикл по действиям, а внутри сделаем перебор по расстановке остальных скобок теперь рассмотрим, какое действие может быть последним: 1. + здесь все просто: нужно максимизировать то, что слева, и то, что справа, решаются эти задачи независимо 2. - здесь тоже все просто: нужно максимизировать то, что слева, и минимизировать то, что справа 3. * здесь менее приятный случай (из-за того, что в зависимости от знака одного множителя нужно либо минимизировать, либо максимизировать другой), тут можно просто решить 4 задачи: min и max первого, min и max второго, и выбрать один из 4х вариантов
да в остальных случаях будут отрицательные результаты (меньше нуля -------------------- qqq |
|||
|
||||
| Akina |
|
|||
|
Советчик ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 20581 Регистрация: 8.4.2004 Где: Зеленоград Репутация: 2 Всего: 454 |
Не факт 2*3+3*2 2*(3+3)*2 -------------------- О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума. |
|||
|
||||
| maxim1000 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 2 Всего: 110 |
гы-гы, факт я описывал только "внешнюю" операцию (ту, которая выполняется последней в первом случае все, действительно, просто во втором "внешней" операцией является умножение, так что используется 3-е правило а после того, как внешняя операция разделила выражение (ну, еще не совсем выражение, скорее, выражение без скобок) на два независимых (если не считать зависимости, описанной в пункте 3), в каждом из них можно перебирать свою внешнюю операцию -------------------- qqq |
|||
|
||||
| En_t_end |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2074 Регистрация: 4.12.2004 Репутация: нет Всего: 20 |
На этот вопрос с программерской точки зрения знает ответ ~FOX~, он в одной из тем флейма хвастался
ЗЫ 3.0 - не совсем удачное число |
|||
|
||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 1 Всего: 317 |
maxim1000 а что если выражение может быть сколь угодно большим, операции: +, -, *, /, %(модуль), -(унарный минус). Какова логика теперь?
-------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| Fedor |
|
|||
![]() Днепрянин ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 2090 Регистрация: 8.2.2003 Где: Великий Репутация: 1 Всего: 32 |
перебор. Чистый. Это классическая задача.
-------------------- Мы - Днепряне. Мы всех сильней. |
|||
|
||||
| Fixin |
|
|||
![]() Ёжик ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1357 Регистрация: 6.1.2004 Репутация: нет Всего: 18 |
Но для перебора нужны кие-то ограничения.
|
|||
|
||||
| Fixin |
|
|||
![]() Ёжик ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1357 Регистрация: 6.1.2004 Репутация: нет Всего: 18 |
Основная проблема, как организовать разбор выражения по-проще, вставить-то скобки потом можно.
Добавлено @ 11:35 И еще. Может пробовать расставить скобки по каждому знаку действия? |
|||
|
||||
| Sardar |
|
||||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 1 Всего: 317 |
Дык это регулярные выражения(можно LL(1) разбор). Делаешь лексический анализ на табличноуправляемом ДКА, получил числа и операторы(лексемы). Затем по лексемам собираешь деревья выражений, это по разному сделать можно. Если нужно как можно проще и изменятся в будущем особо не будет, то закодируй в ручную лексер. Приемр на JS за 5 минут:
С табличноуправляемым разбором покажу попозже. -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
||||
|
|||||
| Sardar |
|
||||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 1 Всего: 317 |
Не знаю нужно ли это, примера выше вполне хватает. Но если нужен лексический анализ посложнее, то используем теорию(обращатся на http://www.softcraft.ru)
Сначала придумывал реги:
Затем нарисовал по ним граф(по диаграме Вирта). ДКА строил ручками по нарисованному графу, в уме создавал множества first/follow. Для такой маленькой таблички это еще возможно, при более сложной грамматике юзаем соответствующие инструменты(GOLDParser, flex и т.п.)
Состояния 6 и 7 не внесенны в таблицу, мы просто устанавливаем начальное состояние вручную state=0 Цикл разбора бесконечный, прерывается автоматом, потому за ним нужно хорошо следить, а то можешь уйти в бесконечный цикл Для парсинга числа я использовал parseFloat, ты можешь при получении числа вторично пройтись по нему и распарсить встроенными функциями, либо парсить на состояниях 1-5 Это была лексика, теперь нужно это всё собрать до четвёрок либо любого другого представления со всеми возможными вариантами раставления скобок. Затем всё выполнить, найти требуемый результат и выбрать наиболее подходящее выражение. -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
||||
|
|||||
| Fixin |
|
|||
![]() Ёжик ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1357 Регистрация: 6.1.2004 Репутация: нет Всего: 18 |
Прикольно. С такой теорией любая олимпиада = "нефиг нафиг пофиг"
|
|||
|
||||
| maxim1000 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 2 Всего: 110 |
количество комбинаций расстановки скобок конечно, поэтому количество всевозможных значений выражения конечно, а значит, из них можно выбрать максимум с операциями типа % действительно проблема - зависимость не монотонна по аргументам, там так не получится... -------------------- qqq |
|||
|
||||
| Fixin |
|
|||
![]() Ёжик ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1357 Регистрация: 6.1.2004 Репутация: нет Всего: 18 |
В условии такех вообще не имеется. Я решил попробовать грузить цифры в один массив, а знаки в другой. Изменяем массив со знаками, сливаем, проверяем на макс, сохр. копию, идем дальше...
Но, хр-вато как-то |
|||
|
||||
| Fixin |
|
|||
![]() Ёжик ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1357 Регистрация: 6.1.2004 Репутация: нет Всего: 18 |
А действительно. Так как "+" и "-" равнозначны, то смысл есть только относительно "*" скобки ставить, больше они нигде роли не играют. Надеюсь. Если неправ, то скажите.
|
|||
|
||||
| maxim1000 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 2 Всего: 110 |
(1-2)+3 1-(2+3) -------------------- qqq |
|||
|
||||
| Fixin |
|
|||
![]() Ёжик ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1357 Регистрация: 6.1.2004 Репутация: нет Всего: 18 |
Уже догадался. Обломчик.
Добавлено @ 21:32 Задолбался. Не могу заставить ету штуку все варианты строить. Тут нужна рекурсия или псевдорек., что-то вообще ничего не получается. Хоть словами опишите алгор. Извиняюсь за ламерство. |
|||
|
||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 1 Всего: 317 |
Блин сижу и гадаю как порешать, никогда таким не занимался, алгоритм придумал сам, так что извиняюсь за глупости
Хранить все деревя выражения крайне не эффективно, ибо всю память сожрёт. Вот что я надумал, может завтра выложу код:
Сначала убираем все приоритеты операций, мы расставляем все скобки. Заводим для каждого уровня дерева целый счётчик, присваиваем ему 1. Считаем сколько в выражении чисел, делим на два, вот это максимальная разрядность счётчика. В примере это 3 бита. Взяли значение счётчика текущего уровня, раскладываем на биты и идём вдоль битового ряда и ряда чисел нашего выражения. Если бит равен 0, то пропускаем число, иначе обьеденяем текущее число и следующее в ноду Ri. Переходим на уровень выше, повторяем действия выше. Так продолжается до корня. Вычисляем выражение, это очень просто если ты строил дерево на обéктах операторах, тогда вызываем у корня выполнить, а тот в свою очередь рекурсивно опросит потомков и так до самых листьев. Если пишем не на обьектно ориентированном языке, то строим линейное дерево на тройках, такое представление очень легко вычислить. Посчитали, сохранили где нибудь результат + все счётчики с уровней. Таким образом мы можем сравнить результаты и если надо, востановить дерево. Построенное и уже не нужное дерево удаляем, освобождая память под следующее дерево. Инкрементируем счётчик первого уровня и повторяем все действия снова. Как только счётчик первого уровня переполнится, инкрементируем счётчик второго уровня, по такому правилу и выше по дереву. Посчитали, ОК, теперь всё по новой, но связывать узлы по счётчику будем не слева на право, а с права на лево. Последнее дерево можно не генерить, оно такое же как и при первой половине вычислений. Всё посчитали, теперь достаём нашь своп файл и т.п. куда мы сохраняли результаты вычисления дерева и счётчики. Находим тот результат, который нужен(наибольший, наименьший, по указанию васи пупкина...). Отсюда находим все вариации деревьев которые дают этот результат. По счётчикам ставим скобки точно также как строили деревья. -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| maxim1000 |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Участник Сообщений: 3334 Регистрация: 11.1.2003 Где: Киев Репутация: 2 Всего: 110 |
хм... честно говоря, не понял алгоритма
есть два пути (как, впрочем, и в большинстве случаев): снизу (по первой выполняемой операции) и сверху (по последней) 1. сверху (я уже описал): типичная рекурсия, перебираем последнюю операцию (которая делит выражение на две части), вызываем минимизацию/максимизацию для частей, выбираем максимум 2. снизу (тоже, вобщем-то, рекурсия): выбираем первую операцию, которая будет выполнена, заменяем пару чисел и знак между ними на результат операции, получаем N новых выражений (потому, как первую операцию можно выполнить N способами, N - количество операций), к каждому применяем тот же алгоритм (эти выражения стали короче на 1 операцию) теперь будем думать: нам нужен быстрый алгоритм или алгоритм с неболшим использованием памяти? 1. небольшое использование памяти: тогда рекурсия, максимальное использованием памяти - приблизительно N*Length(s)/2 2. скорость: дело в том, что алгоритм можно ускорить, пожертвовав некоторым объемом памяти, получается так, что граф разбора деревом не является (точнее не совсем является), т.к. выражения: (1+1)-(2+2) (первая операция - над 1-цами) и (1+1)-(2+2) (первая операция - над 2-ками) логично было бы считать одинаковыми (а тогда уже и обрабатывать один раз) но к ним можно прийти двумя путями, а значит, это не дерево вот на отказе от повторной обработки и получится ускорение но для этого надо хранить все результаты обработки каждого такого выражения (вот и наша жертва - память) -------------------- qqq |
|||
|
||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 1 Всего: 317 |
Права пословица, утром голову глючит меньше чем вечером
Дерево можно не строить! На каждом уровне мы имеем ряд чисел, все связанные узлы вычисляем и получаем новый ряд, в котором как миннимум на одно число стане меньше. Над новым рядом повторяем те же операции и опять вычисляем узлы. Так до тех пор пока в ряду не останется всего одно число, которое и будет результатом. Количество счётчиков равно высоте самого высокого дерева, т.е. N-1, где N это количество чисел в выражении. Самое низкое дерево получаем если обьеденяем как можно больше пар из соседних элементов. Добавлено @ 11:04 Дерево точно можно не строить, извиняюсь если не ясно описал, попробую обьяснить кодом вечером, сейчас я на работе, перерыв -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 1 Всего: 317 |
Если усложним задачу: в выражении могут встречатся негативные числа и уже проставленные скобки: 1+-3-(45/7+12*6+9)*(-1)+34
Негативные числа распознаются парсером, он же и номрализует их до вида (- число). Мы получаем ряд готовых чисел. По грамматике разбора генерим в конце выражение назад. Уже существующие скобки убирать нельзя. Тогда мы вычилсяем содержимое скобок отдельно(подвыражение) и получаем множество результатов {число:счётчики}. Заменяем все вхождения выражений в скобках на Si, где для каждой Si вычислили своё множество результатов. Ну а затем работаем с текущим деревом подставляя на места Si числа из связанного множества. Таким образом можно иметь скольугодно уже ресставленных скобок как угодно вложенных друг в друга. -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| Fixin |
|
|||
![]() Ёжик ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1357 Регистрация: 6.1.2004 Репутация: нет Всего: 18 |
Спасибо, за что есть
Буду разбираться. Можете порекомендовать теорию по динам(или простому) программингу в электронном виде или имена авторов? Это сообщение отредактировал(а) Fixin - 16.2.2005, 18:12 |
|||
|
||||
| Fixin |
|
|||
![]() Ёжик ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1357 Регистрация: 6.1.2004 Репутация: нет Всего: 18 |
|
|||
|
||||
| Sardar |
|
|||
![]() Бегун ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 6986 Регистрация: 19.4.2002 Где: Нидерланды, Groni ngen Репутация: 1 Всего: 317 |
Приоритеты операций это то что ты сам реализуешь. Если этого не делать, то приоритетов не будет -------------------- Опыт - сын ошибок трудных © А. С. Пушкин Процесс написания своего велосипеда повышает профессиональный уровень программиста. © Opik Оценить мои качества можно тут. |
|||
|
||||
| Fixin |
|
|||
![]() Ёжик ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 1357 Регистрация: 6.1.2004 Репутация: нет Всего: 18 |
Я не понял куда убираем-то? |
|||
|
||||
![]()
|
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Интересные и занимательные задачи по программированию | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |