Hi, All.
К сожалению, я плохой математик Задачу наверняка кто-то когда-то решал, но я не представляю где искать решение... Если кто знает - ткните носом, плиз.
Единичная окружность, на ней непредсказуемым образом расположены N (от 3 до 10**4) точек (заданы массивом углов), задающие соответственно N векторов V. Необходимо найти массив коэффициентов при векторах K, таких чтобы сумма Ki*Vi по i от 1 до N была бы =0 . (С заранее заданной точностью, поскольку решаем в цифре)
Понятно, что задача либо не имеет решения (если все точки поместились на одной полуокружности), либо имеет их бесконечно много.
Не интересуют решения, где хоть один Ki=0 - ибо это эквивалентно уменьшению N .
Предпочтительно, чтобы соседние коэффициенты были "близки". Это пожелание, а не требование - решение, где "соседние" Ki отличаются на 10% - оно "лучше" чем то решение, где они отличаются в 100 раз. Ну и "для порядку" пусть 0<=Ki<=1 ;
Я набросал довольно тупой алгоритм: сначала присвоили всем Ki=1, подсчитали отдельно сумму Sin и Cos, затем с "выпирающей стороны" слегка уменьшили коэффициенты, посмотрели удовлетворяет ли нас результат по точности, if not - повторить. Принципаиально - работает, но медленно - ошибка уменьшается в 2-3 раза за цикл, крутить его 10-20 раз - долговато получается...
Проблема -
а) в большом диапазоне N. Понятно, что при N=3 можно и аналитически решать, но при 1000 это неоправданный расход ресурсов, как мне кажется.
б) в характеристике распределения этих точек - оно непредсказуемо, но НЕ случайно, т.е. даже при максимальных N нельзя расчитывать на какую-либо равномерность. Могут распределиться равномерно, а могут - две на одной стороне и все остальные напротив.
А алгоритм должен работать при любом из таких крайних вариантов.
Подайте идеек, кто сколько может
Не знаю как назвать
HINT: Чётче формулируйте условия. Вещи очевидные для Вас могут быть непонятны другим людям.
В вашем тексте непонятных мест много, поэтому даже задать уточняющие вопросы сложно.
HINT2: Приведите пример(ы) правильного/неправильного решения.
В вашем тексте непонятных мест много, поэтому даже задать уточняющие вопросы сложно.
HINT2: Приведите пример(ы) правильного/неправильного решения.
Ну я бы наверное делал так, может неправильно но навскидку:
Есть у нас N векторов...
С начала проверяем возможно ли это сделать, для этого достаточно чтобы для каждого вектора выполнялось условие:
Если с вектора сделать диагональ (образно сказано, продлить в другую сторону на туже длину) и рассмотреть оба получившихся полукруга, то в каждом из них должен быть хотя бы один из векторов.
Если это сделать можно, тогда делаем так:
Берем первый вектор, разбиваем им круг пополам, находим половину где больше векторов (если поровну то все равно), из этой половины находим вектор который ближе всего к нашему (наименьший угол между ними).
Их складываем, получая их биссектрису, хотя не важно как их сложить (Имеется ввиду получаем новый вектор в их промежутке, коэффициенты желательно подбирать такие чтобы длина нового вектора была 1 чтоб не париться с длинами). Получаем новый вектор M для которого делаем снова, разбили и нашли.
Так делаем пока не останется три вектора, осталось три вектора - посчитали коэффициенты которые надо чтобы получился 0.
Ну и соответственно все коэффициенты запоминать по ходу.
Запоминать просто, цикл делается просто.
Алгоритм будет работать если надо можно объяснить математически.
Вот только на счет коэффициентов не уверен как там все хорошо будет (в смысле рядом)
Есть у нас N векторов...
С начала проверяем возможно ли это сделать, для этого достаточно чтобы для каждого вектора выполнялось условие:
Если с вектора сделать диагональ (образно сказано, продлить в другую сторону на туже длину) и рассмотреть оба получившихся полукруга, то в каждом из них должен быть хотя бы один из векторов.
Если это сделать можно, тогда делаем так:
Берем первый вектор, разбиваем им круг пополам, находим половину где больше векторов (если поровну то все равно), из этой половины находим вектор который ближе всего к нашему (наименьший угол между ними).
Их складываем, получая их биссектрису, хотя не важно как их сложить (Имеется ввиду получаем новый вектор в их промежутке, коэффициенты желательно подбирать такие чтобы длина нового вектора была 1 чтоб не париться с длинами). Получаем новый вектор M для которого делаем снова, разбили и нашли.
Так делаем пока не останется три вектора, осталось три вектора - посчитали коэффициенты которые надо чтобы получился 0.
Ну и соответственно все коэффициенты запоминать по ходу.
Запоминать просто, цикл делается просто.
Алгоритм будет работать если надо можно объяснить математически.
Вот только на счет коэффициентов не уверен как там все хорошо будет (в смысле рядом)
-
- Сообщения: 2
- Зарегистрирован: 16 сен 2009, 12:24
Спасибо, мысль интересная, надо ее подумать.
Но мне но совсем понятен принцип выбора пар векторов для сложения. Легко представляю ситуацию, когда неправильным выбором первой пары мы можем решаемый случай превратить в нерешаемый: скажем, точки на 3 часа, 8, 11, 0. Если мы возьмем 3 и 0 с равными К, суммарный будет в направлении 1:30 - оп, задача стала нерешаема...
Но мне но совсем понятен принцип выбора пар векторов для сложения. Легко представляю ситуацию, когда неправильным выбором первой пары мы можем решаемый случай превратить в нерешаемый: скажем, точки на 3 часа, 8, 11, 0. Если мы возьмем 3 и 0 с равными К, суммарный будет в направлении 1:30 - оп, задача стала нерешаема...
Да согласен такой вариант будет плоховат.. не прокатит...
Не получится из-за того, что для вектора который выбрали - наша точка М была единственная в полукруге...
Можно сделать проверку, если это так, то точку М оставить и брать следующую за ней (ту что хотели прибавить) и ищем что прибавить к ней, тогда получится, что обязательно останется хотя бы по одной точке в каждом полукруге... Вот только надо подумать не может ли быть варианта что оно зациклится.
В примере будет выглядеть так -> берется точка 3, смотрим что к ней надо прибавлять 0, но для 0 -> 3ка единственная, идем дальше, выбираем 0 и смотрим что к ней надо прибавить тогда 11, что нам подходит...
А если сделать так...
Ищем минимальный угол (из всех что есть)... если напротив в секторе противоположном нету точки (может быть максимум одна точка), то берем по середине, если есть, то выбираем так, чтобы та точка отнеслась к той половине где меньше точек...
P.S интересная задачка =) могу помочь с реализацией =) (аська в профиле есть)
-----------
Прикинул, зацикливания не будет, оно возможно только при 3-х точках
Не получится из-за того, что для вектора который выбрали - наша точка М была единственная в полукруге...
Можно сделать проверку, если это так, то точку М оставить и брать следующую за ней (ту что хотели прибавить) и ищем что прибавить к ней, тогда получится, что обязательно останется хотя бы по одной точке в каждом полукруге... Вот только надо подумать не может ли быть варианта что оно зациклится.
В примере будет выглядеть так -> берется точка 3, смотрим что к ней надо прибавлять 0, но для 0 -> 3ка единственная, идем дальше, выбираем 0 и смотрим что к ней надо прибавить тогда 11, что нам подходит...
А если сделать так...
Ищем минимальный угол (из всех что есть)... если напротив в секторе противоположном нету точки (может быть максимум одна точка), то берем по середине, если есть, то выбираем так, чтобы та точка отнеслась к той половине где меньше точек...
P.S интересная задачка =) могу помочь с реализацией =) (аська в профиле есть)
-----------
Прикинул, зацикливания не будет, оно возможно только при 3-х точках
Ну, теперь задача яснее
Мне представляется, что можно вычислить коэффициенты точно и достаточно просто.
1. Находим результирующий вектор.
2. Для простоты дальнейших действий "поворачиваем" весь массив так, чтобы результирущий вектор был на 0 часов. Далее работаем с "повернутым" массивом.
3. Отдельно для верхней и нижней частей массива находим результирующие вектора. У этих двух векторов будет одинаковое абсолютное значение по оси Х (но с разными знаками). А абсолютное значение векторов по оси Y будет больше у верхнего чем у нижнего в K=Y(верх)/Y(ниж) раз. Но если мы сейчас просто поделим все верхние вектора на К, то у нас также уменьшится значение по оси Х для верха и общий результирующий не будет нулевым.
4. Чтобы этого избежать, делим верхнюю часть на левую и правую четверть и находим для этих четвертей результирующие вектора. Чтобы не менялось значение по оси Х для всей верхней половины должно выполняться условие: К(лев) х Х(лев) + К(прав) х Х(прав) = Х(лев) + Х(прав). Одновременно, также должно выполняться условие: К(лев) х Y(лев) + К(прав) х Y(прав) = К(из пункта 3.) х (Y(лев) + Y(прав)).
5. Решаем систему уравнений и, собственно, всё. Получаем два коэффициента - К(лев) и К(прав) - на которые надо поделить соответствующие четверти.
ЗЫ. Может быть, что в верней части повернутого массива все вектора будут находиться только в одной четверти. Тогда надо будет подобные вычисления делать с нижней частью.
Мне представляется, что можно вычислить коэффициенты точно и достаточно просто.
1. Находим результирующий вектор.
2. Для простоты дальнейших действий "поворачиваем" весь массив так, чтобы результирущий вектор был на 0 часов. Далее работаем с "повернутым" массивом.
3. Отдельно для верхней и нижней частей массива находим результирующие вектора. У этих двух векторов будет одинаковое абсолютное значение по оси Х (но с разными знаками). А абсолютное значение векторов по оси Y будет больше у верхнего чем у нижнего в K=Y(верх)/Y(ниж) раз. Но если мы сейчас просто поделим все верхние вектора на К, то у нас также уменьшится значение по оси Х для верха и общий результирующий не будет нулевым.
4. Чтобы этого избежать, делим верхнюю часть на левую и правую четверть и находим для этих четвертей результирующие вектора. Чтобы не менялось значение по оси Х для всей верхней половины должно выполняться условие: К(лев) х Х(лев) + К(прав) х Х(прав) = Х(лев) + Х(прав). Одновременно, также должно выполняться условие: К(лев) х Y(лев) + К(прав) х Y(прав) = К(из пункта 3.) х (Y(лев) + Y(прав)).
5. Решаем систему уравнений и, собственно, всё. Получаем два коэффициента - К(лев) и К(прав) - на которые надо поделить соответствующие четверти.
ЗЫ. Может быть, что в верней части повернутого массива все вектора будут находиться только в одной четверти. Тогда надо будет подобные вычисления делать с нижней частью.
Еще вариант
А если сделать так:
1) Выбрать три вектора для которых выполняется условие
2) Сложить все остальные вектора
3) Решить для 4-х векторов
Какой бы не получилась сумма мы сможем подобрать коефициенты
А если сделать так:
1) Выбрать три вектора для которых выполняется условие
2) Сложить все остальные вектора
3) Решить для 4-х векторов
Какой бы не получилась сумма мы сможем подобрать коефициенты